Date: Fri, 5 Dec 2025 12:17:04 +0000
On Fri, 5 Dec 2025 at 11:03, Juan Lucas Rey wrote:
> Hello,
>
> Here is an example code that shows:
>
> -the original issue reproduced as shown in
> https://cplusplus.github.io/LWG/issue2524
For anybody else trying it, the original problem can be reproduced with
libc++ but not libstdc++, because libstdc++ has a workaround in
std::generate_canonical which returns the largest value of RealType which
is less than RealType(1).
>
> - std2::exponential_distribution, using internally
> std2::generate_canonical_centered and NOT showing the issue
> -other values are the same
>
> I have added a double template parameter "limit" to
> "std2::generate_canonical_centered". to allow maximum backwards
> compatibility, that value should be close to 1.
> setting that value to 0.5 is maybe more elegant, but less backward
> compatible.
>
So it's just a hardcoded "use a different calculation if the result would
be greater than LIMIT" branch inside generate_canonical_centred. OK. But
isn't that alternative path taken for a tiny fraction of the values from
the URNG? Something like 1e-8 of the full range? So it's not symmetrical
around zero? Instead it seems to return values in the range [-1e-08, 1.0).
I thought the proposal was for a symmetric distribution around zero? So I
think I'm failing to understand the proposal.
I'm not sure how very occasionally returning values below zero, i.e. below
the expected range of [0,1), is better than very occasionally returning
1.0, i.e. above the expected range.
So again, I think the idea of an alternative function that is symmetrical
around zero is interesting. But I don't understand the backwards
compatibility argument at all. It seems that your solution returns the same
values as the old spec for std::generate_canonical in most cases, but just
has a different form of failure in the problematic cases. Sure, we can
adjust std::exponential_distribution to cope with the "bad" results, but
std::generate_canonical_centred with a limit of 0.999999 is not centred,
and fails to meet the original contract for std::generate_canonical.
Unless I'm misunderstanding something, I think this proposal would make
more sense if you dropped the backwards compatibility claims, and just
demonstrated why a symmetric-around-zero distribution has valuable
properties. But you should also show how it would be used by the rest of
the library. You've shown how std::exponential_distribution can be adapted
to work with (-0.5,0.5] but what about std::uniform_real_distribution and
std::bernoulli_distribution, etc. I count 26 uses of generate_canonical in
libstdc++'s <random>, should they all be changed to use
generate_canonical_centred? Wouldn't that mean an extra branch and extra
logic in every one of them, to handle the negative half of the range? Or
maybe there's no benefit to some distributions and they should continue to
use std::generate_canonical? I think the proposal needs to explain the
extent of the changes that would result from introducing this new function.
Or maybe I'm just misunderstanding something ... in which case that
suggests something in the proposal needs to be clarified.
> Hello,
>
> Here is an example code that shows:
>
> -the original issue reproduced as shown in
> https://cplusplus.github.io/LWG/issue2524
For anybody else trying it, the original problem can be reproduced with
libc++ but not libstdc++, because libstdc++ has a workaround in
std::generate_canonical which returns the largest value of RealType which
is less than RealType(1).
>
> - std2::exponential_distribution, using internally
> std2::generate_canonical_centered and NOT showing the issue
> -other values are the same
>
> I have added a double template parameter "limit" to
> "std2::generate_canonical_centered". to allow maximum backwards
> compatibility, that value should be close to 1.
> setting that value to 0.5 is maybe more elegant, but less backward
> compatible.
>
So it's just a hardcoded "use a different calculation if the result would
be greater than LIMIT" branch inside generate_canonical_centred. OK. But
isn't that alternative path taken for a tiny fraction of the values from
the URNG? Something like 1e-8 of the full range? So it's not symmetrical
around zero? Instead it seems to return values in the range [-1e-08, 1.0).
I thought the proposal was for a symmetric distribution around zero? So I
think I'm failing to understand the proposal.
I'm not sure how very occasionally returning values below zero, i.e. below
the expected range of [0,1), is better than very occasionally returning
1.0, i.e. above the expected range.
So again, I think the idea of an alternative function that is symmetrical
around zero is interesting. But I don't understand the backwards
compatibility argument at all. It seems that your solution returns the same
values as the old spec for std::generate_canonical in most cases, but just
has a different form of failure in the problematic cases. Sure, we can
adjust std::exponential_distribution to cope with the "bad" results, but
std::generate_canonical_centred with a limit of 0.999999 is not centred,
and fails to meet the original contract for std::generate_canonical.
Unless I'm misunderstanding something, I think this proposal would make
more sense if you dropped the backwards compatibility claims, and just
demonstrated why a symmetric-around-zero distribution has valuable
properties. But you should also show how it would be used by the rest of
the library. You've shown how std::exponential_distribution can be adapted
to work with (-0.5,0.5] but what about std::uniform_real_distribution and
std::bernoulli_distribution, etc. I count 26 uses of generate_canonical in
libstdc++'s <random>, should they all be changed to use
generate_canonical_centred? Wouldn't that mean an extra branch and extra
logic in every one of them, to handle the negative half of the range? Or
maybe there's no benefit to some distributions and they should continue to
use std::generate_canonical? I think the proposal needs to explain the
extent of the changes that would result from introducing this new function.
Or maybe I'm just misunderstanding something ... in which case that
suggests something in the proposal needs to be clarified.
Received on 2025-12-05 12:17:24
