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 #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 <[email protected]>
ldexpf called the host ldexp on a float, which computes in double and
sets ERANGE only when the double result leaves the double range, so
ldexpf(0x1.3d1c6p-95f, 1262) set ERANGE while ldexpf(1.0f, 200) did
not. The titles' ldexpf never sets errno, as their scalbnf does not.
ldexpf now computes like scalbnf: on 100,000 random arguments it
matches the libc.prx of PPSA07923 and PPSA05916 in every value and
errno, against 63,957 errno differences before.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2^-149 and -2^-141 are exact subnormal powf results that raise no flag,
and 3^-90 is an inexact one that raises FE_UNDERFLOW and FE_INEXACT;
none sets errno, as in the libc.prx of PPSA07923 and PPSA13934.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
powf returns sn * tiny * tiny for an underflowing result, as FreeBSD
msun's e_powf.c does, so that the multiplication raises the underflow
and inexact flags. Math.cpp is built without -frounding-math and tiny
was a local constant, so GCC folded the product to zero at compile time
and no flag was raised; titles' libc.prx raises FE_UNDERFLOW with ERANGE.
Read tiny through a volatile, so the product is computed at run time.
The results and errno are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
For a negative integer and -inf, titles' libc.prx returns the x86
default NaN (0xffc00000) from tgammaf, where the host tgamma returns
0x7fc00000. Return the titles' NaN when the result is NaN and the
argument is not; errno and the raised flags are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
For |x| > 1, the infinities and NaN, titles' libc.prx stores EDOM and
raises FE_INVALID from acosf, quiet NaN included, and asinf also
raises FE_INVALID for a quiet NaN. acosf returned the same NaN bits
without either, and asinf set errno but raised nothing for a quiet NaN.
Both now call _Feraise with the invalid exception, which stores EDOM
and raises the flag in both units; the results are unchanged.
The acosf test asserted the old errno-preserving behaviour from a
FreeBSD reading; it now checks the titles' EDOM and FE_INVALID.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The only conflict was in GuestMath.cpp, where main's sinh tests and this
branch's asinh tests were inserted at the same place. Keep both: the asinh
checks follow the sinh ones.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
tgammaf goes through the host's double tgamma, and Windows UCRT sets
ERANGE at the poles and on double overflow and EDOM for -inf. The
libc.prx that titles ship sets EDOM for a finite negative integer and
leaves errno unchanged for every other argument, including 0, -0, -inf
and overflow. tgammaf now does the same; results are unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
strtof and wcstof returned the default quiet NaN for any NAN(...)
sequence. The libc.prx bundled with eleven titles reads the payload as
its strtod does, but into one 32-bit word: a blank after the first group
of digits ends it, the first 8 digits are kept and cut to 24 bits, the
result goes under the quiet bit with the sign, and a zero payload
becomes 1. HexNanPayload now takes the word count, two for double and
one for float, and the NaN table test checks the measured float bits
and end for all 64 inputs.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Conflicts with main's newer libc changes resolved without changing either
side: the debt list keeps each side's entry changes (per entry, deletions
included), GuestMath.cpp keeps both sides' test functions and calls, and
Math.cpp differs from main by exactly this branch's own changes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
rand and rand_r both used FreeBSD's do_rand (Park and Miller on
state % 0x7ffffffe + 1, minus one), so rand returned values up to
0x7ffffffd and rand(), rand_r() and every seeded sequence differed
from the console. The libc.prx that titles ship (the same code in the
copies of PPSA13934, PPSA07923 and PPSA05916, read from disassembly)
uses two different generators:
- rand steps a 64-bit state, initially 1, as
state * 0x5851F42D4C957F2D + 1 and returns (state >> 32) & 0x3FFFFFFF,
so its results stay at or below 0x3FFFFFFF. srand stores the seed
zero-extended as that state.
- rand_r is the minimal standard generator, state * 16807 modulo
2^31 - 1 on the signed 32-bit state (1 gives 16807, 282475249,
1622650073), and a zero state becomes 0x2AE1B767.
guest_math now expects those results: the rand_r chain from 1, the
zero and 0x7FFFFFFF states, rand after srand(1), srand(0) and
srand(0xFFFFFFFF), and rand's range over 1000 calls. Its previous
checks expected FreeBSD's values and rand matching rand_r.
Co-Authored-By: Claude Opus 5.5 <[email protected]>