[PATCH 2/3] math: Optimize dbl-64 remainder implementation
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri Sep 12 14:39:07 GMT 2025
On 12/09/25 11:17, Wilco Dijkstra wrote:
> Hi Adhemerval,
>
>> + return NAN;
>>>
>>> Since NAN returns a float NaN, wouldn't C99 nan("") be better?
>>
>> Right, I think it should ok and not create a nan call for all targets.
>
> We likely need to do something similar as in fmod though, eg. if one is a NaN
> return x * y (so invalid operation is set), if y is zero or inf, return __math_edom.
Yeah, the x * y is need for !LIBM_SVID_COMPAT (and it explains why I was not see
math failure on x86_64. But, for errno we still use the math/w_remainder_template.c or
math/w_remainder_compat.c which correctly sets the errno.
>>> Since these branches may be fairly hard to predict, it's worth checking whether
>>> this works out better:
>>>
>>> x = (x >= y) ? x - y : x;
>>> x = ((x + x) >= y) ? x - y : x;
>>>
>>> You can always start with x >= y and only use (x + x) or y * 0.5 for the 2nd part.
>>
>> I did not see much difference neither on x86_64 (Ryzen 9) or aarch64 (N1) with
>> recent gcc.
>
> These are running the same input repeatedly which just tests best-case rather than
> average case performance...
>
> I wonder whether we should treat all inputs as workloads and cycle through
> the values rather than just repeating?
I will add the workload tags on the benchtests, but I don't think we should microoptimize
this case because the most of time will be spent in fmod function.
>
> On 2nd thought, using conditional moves might not get the round to even part of
> x - n * y quite right, and there is a risk of triggering inexact in computing x - y early.
> I wonder whether we have testcases for these corner cases?
>
>>> In either case, we can remove the if (hy < UINT64_C (0x20000000000000)) by adding
>>> an else after the fmod to handle the case of large y.
>>
>> I am not sure if we can remove it, since it to handle small y.
>
> We can always remove it - small y is only an issue if you use 0.5 * y. If you know y is not
> huge (which is true for the call to fmod), then using x + x instead works.
>
>> I think you mean x == -0.0 and yeah I think it should better indeed.
>
> -0.0 and 0.0 are the same - it appears GCC optimizes it to x == 0.0, but it's still wrong to
> write x == -0.0 since it gives the incorrect impression that it excludes 0.0 when it does not....
Even for -frounding-math? If so I think we should keep the integer checks then.
More information about the Libc-alpha
mailing list