Skip to content

fix: Fix flaky Transform2D random round-trip test tolerance#3917

Merged
spydon merged 3 commits into
mainfrom
worktree-flaky-random-test
May 10, 2026
Merged

fix: Fix flaky Transform2D random round-trip test tolerance#3917
spydon merged 3 commits into
mainfrom
worktree-flaky-random-test

Conversation

@spydon
Copy link
Copy Markdown
Member

@spydon spydon commented May 10, 2026

Description

The `Transform2D random` test was flaky because the tolerance formula in
`transform2dRoundTripUncertainty` used only the local point magnitude, which is wrong
when scale is tiny.

Both `Vector2` and `Matrix4` use `Float32List` storage. The dominant error in
`globalToLocal(localToGlobal(point))` is float32 rounding of the intermediate `Vector2`
returned by `localToGlobal`. That rounding error (`~epsilon * globalMagnitude`) is then
amplified by the inverse transform's factor `matrixNorm / |det|`.

With seed `3633814569`, iteration 0 has scale ~0.001, so `matrixNorm / |det|` ≈ 949 and
the global magnitude is dominated by translation (~7.4) rather than the local point (~0.5).
The old formula produced a tolerance of 9.2e-6 while the actual error was 1.12e-4.

The fix computes the actual intermediate global magnitude and uses it directly:
```
tolerance = 3 * epsilon * globalMagnitude * matrixNorm / |det| + epsilon
```

To reproduce the failure before this fix:
```
flutter test packages/flame/test/game/transform2d_test.dart
--dart-define=RANDOM_SEED=3633814569
```

Checklist

  • [-] I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • [-] I have updated/added relevant documentation in `docs` and added dartdoc comments with `///`.
  • [-] I have updated/added relevant examples in `examples` or `docs`.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

spydon added 2 commits May 10, 2026 18:52
Replace the incorrect statistical error propagation formula with a
derivation based on the actual floating-point error source.

Both Vector2 and Matrix4 use Float32List storage, so the intermediate
global Vector2 returned by localToGlobal is rounded to float32
precision. That rounding error (~epsilon * globalMagnitude) is then
amplified by the inverse transform factor matrixNorm / |det|.

The old formula used only the local point magnitude as a proxy, which
fails when scale is tiny: with scale ~0.001, globalMagnitude is
dominated by translation (~7.4 vs local ~1) and matrixNorm / |det|
reaches ~949, making the actual error ~12x larger than the tolerance.
@spydon spydon enabled auto-merge (squash) May 10, 2026 18:13
@spydon spydon merged commit f2fb407 into main May 10, 2026
8 checks passed
@spydon spydon deleted the worktree-flaky-random-test branch May 10, 2026 18:24
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.

2 participants