diff --git a/OPSTACK-PROGRESS.md b/OPSTACK-PROGRESS.md index 2c4d400..4c0fd46 100644 --- a/OPSTACK-PROGRESS.md +++ b/OPSTACK-PROGRESS.md @@ -451,3 +451,43 @@ in the SDF (lattice edges or `VoxelSDF::Capsule`) or in `SmoothStep01`. small unexplained numeric difference, and those do not get smaller when you build on them. --- + +## 2026-07-27 — CORRECTION: hypothesis 3 was never tested. My error, not Jahni's. + +**`FPSemantics = FPSemanticsMode.Precise` was set in `Source/VoxelM/VoxelM.Build.cs` — the GAME +module.** `FPSemantics` is a `ModuleRules` property, i.e. **per module**. Every line of density code +lives in the `VoxelForge` module, which was still compiling `/fp:fast`. The float model never +changed for the code under test. + +**So the previous entry is wrong and is retracted:** `/fp:fast` is NOT eliminated. The run that +"reproduced the residue under precise semantics" reproduced it under *fast* semantics, which is +exactly what it should have done and proves nothing. + +**The failure mode, stated plainly because it is the third time in one day:** I accepted "it's with +fpsemantics precise" as fact and reasoned a confident conclusion from it — one paragraph after +writing that the lesson was to instrument rather than assume. The check took one `grep` and I did it +only after Jahni suggested it. **Verify the premise before reasoning from it, especially when the +premise is what makes the conclusion interesting.** + +**Consequently:** the notes in the previous entry saying `AUDIT §C9` and `OPSTACK-PLAN §2.6` are +falsified are themselves withdrawn. Those documents' `/fp:fast` explanation is back to *plausible +and now genuinely about to be tested*. Nothing in them needs changing yet. + +**What changed:** `FPSemantics = FPSemanticsMode.Precise` added to **`VoxelForge.Build.cs`**, clearly +marked as a temporary experiment with removal instructions and a read-the-result guide. + +`VoxelM.Build.cs` can keep or drop its copy — it is harmless either way and irrelevant to this test. + +**One build now answers everything**, because the WORST-POINT DUMP instrumentation is already in: + +| Result | Meaning | Next | +|---|---|---| +| 454 → **0** | the FP model WAS the cause | remove the line; decide separately whether precise is worth its cost on the hot path (needs a profile) | +| 454 → **454** | real logic difference | remove the line; read the dump — identical recovered carve ⇒ fault after the conversion, differing carve ⇒ fault in the SDF or `SmoothStep01` | + +**UNVERIFIED:** everything about this experiment. + +**Next single action:** rebuild, re-run `MazeEquivalence`, read the two numbers. Phase 1 step 3 stays +paused. + +--- diff --git a/Source/VoxelForge/VoxelForge.Build.cs b/Source/VoxelForge/VoxelForge.Build.cs index 0352c41..cd58d59 100644 --- a/Source/VoxelForge/VoxelForge.Build.cs +++ b/Source/VoxelForge/VoxelForge.Build.cs @@ -11,6 +11,33 @@ public class VoxelForge : ModuleRules // UseExplicitOrSharedPCHs is the modern recommended setting PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + // ============================================================================ + // ⚠️ TEMPORARY EXPERIMENT — 2026-07-27. REMOVE THIS LINE WHEN THE ANSWER IS IN. + // ============================================================================ + // Testing whether the ~1 ULP residue between GetMazeDensity and its operator-stack + // port (VoxelForge.OpStack.MazeEquivalence: 454 of 20000 samples, 0 crossing the + // isosurface) is caused by the compiler being allowed to reassociate identical + // source differently per translation unit. + // + // FPSemantics is a PER-MODULE property. Setting it on the VoxelM game module does + // NOT affect this one — every line of density code lives in VoxelForge, so the + // switch has to be here to mean anything. (That mistake already cost one build and + // one wrong conclusion.) + // + // UnrealBuildTool's Windows default is /fp:fast ("Default is imprecise FP + // semantics", VCToolChain.cs); every Clang target defaults to precise instead. + // + // READ THE RESULT LIKE THIS: + // 454 -> 0 : the FP model WAS the cause. Then decide separately whether to keep + // precise (it costs vectorisation on the density hot path — the thing + // T2.a's SIMD noise work was buying — for an unmeasured amount). + // 454 -> 454 : the FP model is NOT the cause and the difference is real logic. + // Read the WORST-POINT DUMP the test now prints. + // + // EITHER WAY THIS LINE COMES BACK OUT once measured. Keeping /fp:precise on the hot + // path is a decision that needs a profile, not a leftover from a diagnostic. + FPSemantics = FPSemanticsMode.Precise; + // Modules we depend on: // - Core: Basic types (TArray, FString, etc.) // - CoreUObject: UObject system (UCLASS, UPROPERTY, etc.)