Date: Fri, 30 May 2025 11:48:14 -0300
On Friday, 30 May 2025 09:25:17 Brasilia Standard Time Jan Schultke wrote:
> People get overflow-safe, correct rounding functions that yield
> divisors wrong all the time. Obtaining remainders is quite a benign
> operation by comparison, so I don't the "getting things wrong"
> argument is significant for this case.
Maybe a solution is to provide a "get me the remainder associated with this
dividend, divisor and quotient"?
My worry is on choosing the correct one, especially in light of the rounding
to nearest, even, or odd modes. Given a biased set of inputs, unit testing may
fail to notice that the choice of remainder function will fail to produce the
correct mathematical answer at runtime with user input.
> > > Yeah fair point, there's a possibility of introducing a dilemma of
> > > choice.
> > > I'm not really convinced it would be a big problem though. The user can
> > > just not call std::div_to_odd if they don't need it.
> >
> > You did confuse me, because the paper does talk about homogeneising the
> > distribution. So which one should I choose if I want that?
>
> I'm not sure what you're really asking here. Obviously you need to
> understand your domain and what kind of rounding you need to perform a
> certain operation. If you have no idea whether to round to odd or
> round up or to negative infinity, no design of this paper could fix
> that problem for you.
The issue here is that I did not put a lot of thought into the Maths of why
the multiple versions exist. And thus, I ended up viewing this as a somewhat
lay-person who needs to do divisions in a certain way (say, for the timestamp
case), was glad to find that the Standard Library would help me avoid mistakes,
but then ended up *more* confused when I read the part about homogeneising.
This sounds like a good thing to have, but I couldn't figure out a) if I needed
it; and b) how I would go about doing it.
Explaining that will probably not be a part of the Standard text itself, but
it should be in cppreference.com and those usually will take a hint from the
paper that proposed the API. Hence the onus on you to explain the choices,
which you have to justify anyway for the committee.
> In the case of homogenising distribution, that should typically be
> rounded to odd, but that's ultimately user choice.
Why do we need a choice? Is one better than the other? Are there domains in
which one is better than the other?
IEEE 754 has rules on the round-to-nearest that were designed by
Mathematicians. I know the hardware on x86 has up to four extra bits in
intermediate representation to the right of the ULP to decide how roundings
should be performed. Maybe we don't want a one-size-fits-all solution but maybe
we do.
> I still don't see the great potential for confusion here. If the user
> wants to check how many buckets size N they need to fit M elements,
> that's a division towards positive infinity or away from zero. I don't
> buy that the extra functions make it substantially harder. The
> workflow I envision is:
>
> 1. The user understand what rounding mode they need.
> Say, rounding "up"/"ceiling".
> 2. The user looks at the list of available functions and realizes
> that rounding to positive infinity is what they mean by "ceiling" or
> "up", or maybe they were thinking about it in terms of infinity all along.
> 3. Done.
>
> The "too many functions" argument only makes sense if the extra
> functions add potential for confusion, but there's really no way you
> would confuse std::round_to_odd for ceiling/upwards/whatever division.
No, that's not the confusion. Rouding towards positive or negative infinity
(FE_UPWARDS, FE_DOWNARDS), towards zero (FE_TOWARDZERO) are readily
understandable, and a "this is usually what you want" mode of FE_TONEAREST if
possible would be the standard. I'm questioning the rest of them, which add to
the complexity the and the unintuitiveness of API when a user tries to
understand them, especially the distinction between nearest, odd, and even, or
an "away from zero" one.
> People get overflow-safe, correct rounding functions that yield
> divisors wrong all the time. Obtaining remainders is quite a benign
> operation by comparison, so I don't the "getting things wrong"
> argument is significant for this case.
Maybe a solution is to provide a "get me the remainder associated with this
dividend, divisor and quotient"?
My worry is on choosing the correct one, especially in light of the rounding
to nearest, even, or odd modes. Given a biased set of inputs, unit testing may
fail to notice that the choice of remainder function will fail to produce the
correct mathematical answer at runtime with user input.
> > > Yeah fair point, there's a possibility of introducing a dilemma of
> > > choice.
> > > I'm not really convinced it would be a big problem though. The user can
> > > just not call std::div_to_odd if they don't need it.
> >
> > You did confuse me, because the paper does talk about homogeneising the
> > distribution. So which one should I choose if I want that?
>
> I'm not sure what you're really asking here. Obviously you need to
> understand your domain and what kind of rounding you need to perform a
> certain operation. If you have no idea whether to round to odd or
> round up or to negative infinity, no design of this paper could fix
> that problem for you.
The issue here is that I did not put a lot of thought into the Maths of why
the multiple versions exist. And thus, I ended up viewing this as a somewhat
lay-person who needs to do divisions in a certain way (say, for the timestamp
case), was glad to find that the Standard Library would help me avoid mistakes,
but then ended up *more* confused when I read the part about homogeneising.
This sounds like a good thing to have, but I couldn't figure out a) if I needed
it; and b) how I would go about doing it.
Explaining that will probably not be a part of the Standard text itself, but
it should be in cppreference.com and those usually will take a hint from the
paper that proposed the API. Hence the onus on you to explain the choices,
which you have to justify anyway for the committee.
> In the case of homogenising distribution, that should typically be
> rounded to odd, but that's ultimately user choice.
Why do we need a choice? Is one better than the other? Are there domains in
which one is better than the other?
IEEE 754 has rules on the round-to-nearest that were designed by
Mathematicians. I know the hardware on x86 has up to four extra bits in
intermediate representation to the right of the ULP to decide how roundings
should be performed. Maybe we don't want a one-size-fits-all solution but maybe
we do.
> I still don't see the great potential for confusion here. If the user
> wants to check how many buckets size N they need to fit M elements,
> that's a division towards positive infinity or away from zero. I don't
> buy that the extra functions make it substantially harder. The
> workflow I envision is:
>
> 1. The user understand what rounding mode they need.
> Say, rounding "up"/"ceiling".
> 2. The user looks at the list of available functions and realizes
> that rounding to positive infinity is what they mean by "ceiling" or
> "up", or maybe they were thinking about it in terms of infinity all along.
> 3. Done.
>
> The "too many functions" argument only makes sense if the extra
> functions add potential for confusion, but there's really no way you
> would confuse std::round_to_odd for ceiling/upwards/whatever division.
No, that's not the confusion. Rouding towards positive or negative infinity
(FE_UPWARDS, FE_DOWNARDS), towards zero (FE_TOWARDZERO) are readily
understandable, and a "this is usually what you want" mode of FE_TONEAREST if
possible would be the standard. I'm questioning the rest of them, which add to
the complexity the and the unintuitiveness of API when a user tries to
understand them, especially the distinction between nearest, odd, and even, or
an "away from zero" one.
-- Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org Principal Engineer - Intel Platform & System Engineering
Received on 2025-05-30 14:48:19