test: use epsilon comparison for FMA-sensitive API tests#6591
test: use epsilon comparison for FMA-sensitive API tests#6591kimkulling merged 2 commits intoassimp:masterfrom
Conversation
When compiling with -march=znver4 (or any arch with FMA), GCC's default -ffp-contract=fast contracts a*b+c into FMA opportunistically. The same inline math function compiled in the shared library and in the test binary can get different FMA contraction decisions due to different optimization contexts, producing bit-different FP results. Three API tests compare C++ direct calls (inlined into test TU) against C API wrapper calls (through libassimp.so) using EXPECT_EQ (bit-exact), which fails when the compiler contracts differently across TUs. Verified via disassembly: the library uses vfnmadd FMA instructions (3 roundings) while the test binary uses separate vmulss+vsubss (6 roundings) for the same computation. Replace EXPECT_EQ with Equal(epsilon) for the three affected tests: - aiMatrix3FromToTest: use machine epsilon (~1.19e-7) - aiMatrix4FromToTest: use machine epsilon (~1.19e-7) - aiQuaternionFromNormalizedQuaternionTest: use 1e-4 because FMA differences in 1.0-x*x-y*y-z*z can flip a near-zero residual's sign, causing w=0 vs w=sqrt(tiny)≈1e-4 Fixes assimp#6246 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThree unit test assertions were converted from exact matrix and quaternion equality checks to tolerance-based floating-point comparisons using epsilon values, addressing platform-specific numerical precision variations. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
Merged, thank you for your contribution. |
|
Thank you ! |



Summary
Three API tests fail under
-march=znver4(and potentially other FMA-capable architectures) because GCC's-ffp-contract=fast(the default) makes different FMA contraction decisions for the same inline function compiled in different translation units (shared library vs test binary).aiMatrix3FromToTestandaiMatrix4FromToTest: deterministic failure (fixed input vectors)aiQuaternionFromNormalizedQuaternionTest: non-deterministic (~60% failure rate, random input)Root cause (verified via disassembly)
The C API wrappers in
Assimp.cppand the direct C++ calls in the test both invoke the same inline functions from.inlheaders. Under-march=znver4, the compiler generates different machine code in each TU:Shared library (FMA chain, 3 roundings):
Test binary (separate mul+sub, 6 roundings):
This produces bit-different FP results (1-22 ULPs for matrix elements, branch-flip for quaternion
w).Fix
Replace
EXPECT_EQ(bit-exact) with.Equal(epsilon)for the three affected tests. Uses machine epsilon for matrices and1e-4for quaternion (larger because the branch inaiQuaternion(aiVector3D)amplifies tinytdifferences viasqrt).Testing
AssimpAPITest_*tests pass under-march=znver4 -O2(10 repeated runs, 0 failures)AssimpAPITest_*tests pass under generic x86-64 (no regressions)Fixes #6246
🤖 Generated with Claude Code
Summary by CodeRabbit