Skip to content

fix(libc): leave errno unchanged from scalbn and scalbnf on every host - #12681

Merged
adriadam10 merged 1 commit into
boykopovar:mainfrom
JJenkx:windows/libc-scalbn-errno
Oct 29, 2026
Merged

adriadam10 merged 1 commit into
boykopovar:mainfrom
JJenkx:windows/libc-scalbn-errno

Conversation

@JJenkx

@JJenkx JJenkx commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

What

scalbn and scalbnf now leave errno unchanged on every host, as the libc.prx that titles ship does.

Both call the host std::scalbn. On Windows that never sets errno. glibc's scalbn and scalbnf set ERANGE on overflow and on underflow to zero, as rooklz found while reviewing #12676. So on Linux both functions changed errno where the titles don't. They now save and restore errno around the host call, as scalbln, scalblnf and scalblnl already do with ErrnoGuard in MathExact.cpp, and as fmod does.

What the titles do, read natively from PPSA07923's libc.prx (a scratch loader calls its functions by NID), with errno preset to 7:

call titles result titles errno
scalbn(1, 2000) inf unchanged
scalbn(1, -2000), scalbn(1, -1075) 0 unchanged
scalbn(1, -1074) 0x1p-1074 unchanged
scalbnf(1, 200), scalbnf(1, 2000) inf unchanged
scalbnf(1, -200), scalbnf(1, -2000) 0 unchanged
scalbln/scalblnf at the same and at ±(2^47 − 1) as above unchanged
ldexp(1, 2000), ldexp(1, -2000), ldexp(1, -1075), for contrast inf, 0, 0 ERANGE

ldexp (double) keeps setting ERANGE as before, which matches the titles. scalbnl is unchanged: I haven't measured the titles' long double behaviour.

Tested

Windows 11, WinLibs GCC 15.2.0 UCRT r7, Release, main 3a2b919816.

Not tested: a Linux or macOS build or run.

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 (Claude Code)

🤖 Generated with Claude Code

The titles' scalbn and scalbnf never set errno, at any exponent. On
Windows the host scalbn already matches, but glibc's scalbn and scalbnf
set ERANGE on overflow and on underflow to zero (found by rooklz while
reviewing boykopovar#12676), so on Linux they did. Both now keep errno across the
host call, as scalbln and scalblnf already do. CheckScalbnErrno checks
results read from the titles' libc.prx.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@rooklz rooklz 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.

Approving. Your Not-tested section said Linux and macOS weren't run, so I ran both at a561f4e.

Setup. A standalone build of the head scalbn_nid_postfix/scalbnf_nid_postfix bodies and the verbatim CheckScalbnErrno (GuestMath.cpp L656–686). I also built main's one-liners as the control. Each arm also ran a 1,000,000-pair xorshift sweep (random double/float bits, exponents in ±2100 / ±400). The sweep compared values against bare std::scalbn and counted errno changes with errno preset to 7.

host arm CheckScalbnErrno failures sweep errno changes sweep value diffs
Ubuntu 24.04 x86_64, glibc 2.39, GCC 13 head 0 0 0
same main 7 (errno=34) 1,124,062 0
macOS arm64, Apple clang head 0 0 0
same main 0 0 0

So you get the Linux negative control you couldn't get on Windows: the new test is RED on glibc with main's Math.cpp, and green with this PR.

Mutants (glibc):

  • Drop the restore in scalbn only: 3 rows fail.
  • Drop the restore in scalbnf only: 4 rows fail.

Both are killed, so each function is covered on its own.

Other checks:

  • The PR is based on 3a2b919816. git merge-tree is clean against main and pairwise against #12676.
  • check_conventions --base upstream/main passes.
  • The save/restore matches the existing fmod and exp2 pattern in the same file.

Note for a later PR (not blocking): glibc's scalbnl sets ERANGE too. std::scalbn(1.0L, ±20000) gives errno=34, so scalbnl still differs on Linux. Leaving it out until the titles' long-double behaviour is measured is the right call, per the rules.

@adriadam10 adriadam10 self-assigned this Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 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 6085 core/libs/prx/libc/src/Math.cpp
PR 6295 core/libs/prx/libc/src/Math.cpp
core/libs/tests/GuestMath.cpp

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

Copy link
Copy Markdown
Contributor

Windows run of this head a561f4e59176, merged onto main 3a2b9198165 (clean merge, local only), with the selection CI's skipped Windows product job uses: Windows 11, Ryzen 7 5800X, RTX 3080, WinLibs GCC 15.2, Release, BUILD_TESTING=ON. The tree was configured fresh after the merge, then select_tests.py select / ninja -f select.ninja selected / --target libs / select_tests.py ctest --parallel 4 --timeout 120.

AI-assisted: yes (Claude Code)

@adriadam10
adriadam10 merged commit 2e55a9d into boykopovar:main Oct 29, 2026
18 checks passed
@adriadam10

Copy link
Copy Markdown
Collaborator

Checked the errno save/restore around scalbn/scalbnf against the existing ErrnoGuard pattern, the 10 CheckScalbnErrno rows, and the green Conventions/Windows jobs, with rooklz's Linux/macOS run as the glibc evidence; merged.

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