Skip to content

fix(libc): pass the exponent to fma as long double in _LCosh and _LSinh - #13952

Merged
oneandonlydean merged 1 commit into
boykopovar:mainfrom
imellag:fix/libc-long-double-fma-promotion
Nov 5, 2026
Merged

oneandonlydean merged 1 commit into
boykopovar:mainfrom
imellag:fix/libc-long-double-fma-promotion

Conversation

@imellag

@imellag imellag commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

What

_LCosh and _LSinh reduce the argument with std::fma(-exponent, Ln2High, magnitude), where exponent is an int and the other two are long double. That picks the mixed-type std::fma template. In libc++ (macOS, and any clang build that uses libc++) that template computes the promoted type, long double, but then calls __builtin_fma, the double version (__math/fma.h, line 48 of the macOS SDK header; the other mixed-type math templates call __math:: and are fine). So the reduced argument is rounded to 53 bits before expl, and the last ~10 bits of the 64-bit result are wrong. libstdc++ promotes correctly, so Linux and the MinGW build are not affected.

The fix converts the negated exponent to long double once and passes that to both fma calls, so every compiler picks the long double overload. In the built object the two functions now call fmal four times and fma no longer.

Tested

macOS 27.2 (Apple M4 Pro, x86-64 under Rosetta 2), Apple clang 21, Release, guest_math_tests, on main plus the support commits needed to build on macOS.

  • _LCosh(11357, 0x1p-16000) returns 0xc.e2773666cc8cb2dp+380; the test expects 0xc.e2773666cc8cc68p+380. The difference, 0x13b in the last place, matches the reduced argument rounded to 53 bits (0x136 predicted).
  • On this machine guest_math first stops at fmodf (Apple's libm does not raise invalid for fmod(1, 0)), which fix(libc): set EDOM in fmod and fmodf where titles' libc.prx does #10345 fixes. With fix(libc): set EDOM in fmod and fmodf where titles' libc.prx does #10345 applied: without this change GuestMath.cpp stops at the _LCosh(11357.0L, 0x1p-16000L) check 3 out of 3 runs; with this change the whole guest_math passes 3 out of 3.
  • No test change: the existing CheckLongDoubleHyperbolic checks already catch it on libc++.

Checklist

  • Based on current main; no other open PR implements the same functions
  • One topic per PR; follow-ups go in a new PR
  • No comments in code except technical debt
  • Unimplemented paths throw (NotImplemented_nid_no_patch); silent stubs are listed under Silent stubs in their library's technical debt file
  • No notes, investigation .md files or images added to the repository (attach them to this PR)
  • New third-party code is a submodule built from source
  • Generic behaviour, not specific to one title
  • Depends on: none
  • Fixes: none
  • Unblocks: none
  • GPUs tested: n/a
  • AI-assisted: yes

@MarcZX10 MarcZX10 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed — looks good

At head a7e91c26fdca4bbac6cb07817983fc1e1ce7594d, both long-double hyperbolic paths now pass long-double operands to std::fma, addressing the reported narrowing behavior.

What I ran

Reviewed head a7e91c26fdca4bbac6cb07817983fc1e1ce7594d against base 73f4f7e06e4f210a8c6570e335fd654dc0a86134; the merge preview was clean. Local environment: Linux x86_64, Python 3.11.2, GCC 12.2.0. I ran the no-build precheck and inspected both changed call sites and the existing long-double assertions.

python3 tools/pr_precheck.py --repo boykopovar/AnyPS5 --pr 13952
gh pr checks 13952 --repo boykopovar/AnyPS5

Results

Check Result
Diff and conventions Passed
Current-base merge preview Clean
Hosted Windows job Passed
Hosted Ubuntu Debug and Release register-context jobs Passed
Hosted Linux full build Skipped by workflow
Hosted macOS jobs Pending at review time
Author-reported target test On macOS 27.2 / Apple clang 21 / M4 Pro x86-64 under Rosetta, guest_math reportedly failed at the existing _LCosh assertion 3/3 times without this change and passed 3/3 with it, with #10345 applied. I did not run this test independently.
Additional local precheck heuristics Unavailable in the isolated PR snapshot; no conclusion drawn from those checks
Unedited output
All conventions checks passed.
windows	pass	3m22s
register-context (ubuntu-latest, Release)	pass	25s
register-context (ubuntu-latest, Debug)	pass	33s
linux	skipping	0

Sources

The changed long-double reduction paths are in Math.cpp at this head. The existing long-double comparison helper and _LCosh/_LSinh edge assertions are in GuestMath.cpp at this head.

Not verified

I did not run a local build or test. The target-specific macOS result is author-reported; the macOS CI jobs were still pending, and the hosted Linux full build was skipped.

@github-actions github-actions Bot added the libc label Oct 31, 2026
@github-actions

github-actions Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Some comparisons could not be completed because a pull request conflicts with the base branch. Review these shared files manually before concluding that there is no overlap.

Pull request Shared files not compared
PR 6295 core/libs/prx/libc/src/Math.cpp
PR 10113 core/libs/prx/libc/src/Math.cpp
PR 10226 core/libs/prx/libc/src/Math.cpp
PR 10245 core/libs/prx/libc/src/Math.cpp
PR 10250 core/libs/prx/libc/src/Math.cpp
PR 10253 core/libs/prx/libc/src/Math.cpp
PR 10265 core/libs/prx/libc/src/Math.cpp
PR 10274 core/libs/prx/libc/src/Math.cpp
PR 10325 core/libs/prx/libc/src/Math.cpp
PR 10328 core/libs/prx/libc/src/Math.cpp
PR 10345 core/libs/prx/libc/src/Math.cpp
PR 10349 core/libs/prx/libc/src/Math.cpp
PR 10506 core/libs/prx/libc/src/Math.cpp
PR 10510 core/libs/prx/libc/src/Math.cpp
PR 10512 core/libs/prx/libc/src/Math.cpp
PR 10546 core/libs/prx/libc/src/Math.cpp
PR 10565 core/libs/prx/libc/src/Math.cpp
PR 11260 core/libs/prx/libc/src/Math.cpp
PR 11262 core/libs/prx/libc/src/Math.cpp
PR 11266 core/libs/prx/libc/src/Math.cpp
PR 11632 core/libs/prx/libc/src/Math.cpp
PR 11634 core/libs/prx/libc/src/Math.cpp
PR 12122 core/libs/prx/libc/src/Math.cpp

@adriadam10 adriadam10 self-assigned this Nov 1, 2026
@imellag

imellag commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

The two red write-watch jobs (macos-15 and macos-15-intel) are unrelated to this change. They stop at CMake configure with the duplicate write_watch_execute-fault / write_watch_read-fault registration that was on main when they ran; #13220 has since removed it. This PR only changes two std::fma calls in Math.cpp.

AI-assisted: yes

@oneandonlydean
oneandonlydean merged commit 33c810c into boykopovar:main Nov 5, 2026
17 of 19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants