C++ Logo

std-proposals

Advanced search

Re: [std-proposals] solution proposal for Issue 2524: generate_canonical can occasionally return 1.0

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sat, 6 Dec 2025 16:35:27 +0000
On 06/12/2025 08:16, Juan Lucas Rey wrote:
> Hi,
>
> The whole point is that, when u is very close to 1,
> -std::log(result_type(1) - u) * lambda_inv; would have returned
> infinity because "result_type(1) - u" ends up being 0.

Yes, but you effectively achieve that by having a good uniform distribution on (0, 1]. I
agree that it is a much better fit for generating the exponential distribution, as you get
your increased resolution near the singularity, without including the singularity.

I don't see why you need a centered uniform distribution to generate a good uniform
distribution on (0, 1], but maybe it's more versatile in general.>
> by representing that difference by -u, that situation is avoided, so
> there IS increased resolution. -u can be represented by subnormal
> numbers, and std::log is able to give very good values for those
> subnormal numbers.Yes, but that's equally true for generating a good uniform distribution on (0, 1], and use
-log(u) for the whole range.

I see that -log(1 - u) solution with u being uniform on [0, 1) has still quite a distorted
tail distribution. This solution can't produce a result larger than 36.7f for floats for
lambda=1. While the theoretical probability to produce larger results than this is small,
it's not academically small.

>
> on your second comment: "makes the distribution less accurate near 0,
> as it skips over a lot of representable values", could you develop
> further?

Scratch that, I made a mistake there.

Lénárd

>
> Thanks,
> Lucas
>
> On Sat, 6 Dec 2025 at 01:09, Lénárd Szolnoki <cpp_at_[hidden]> wrote:
>>
>>
>>
>> On 05/12/2025 22:32, Lénárd Szolnoki via Std-Proposals wrote:
>>>
>>>
>>> On 04/12/2025 19:05, Juan Lucas Rey via Std-Proposals wrote:
>>>> in the current proposal,
>>>> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p0952r2.html
>>>>
>>>> it is mentioned "In particular, code that depends on a specific
>>>> sequence of results from repeated invocations, or on a particular
>>>> number of calls to the URBG argument, will be broken."
>>>>
>>>> This solution avoids breaking this.
>>>
>>> In the attached proposal within the implementation of exponential_distribution you have:
>>>
>>> const auto u
>>> = std::generate_canonical_centered<
>>> result_type,
>>> std::numeric_limits<result_type>::digits
>>> >(g);
>>> if (std::copysign(1.0, u) > 0) {
>>> return -std::log(result_type(1) - u) * lambda_inv;
>>> } else {
>>> return -std::log(-u) * lambda_inv;
>>> }
>>>
>>> This is exactly equivalent to:
>>>
>>> const auto u = ...
>>> const auto u2
>>> = std::copysign(1.0, u) > 0
>>> ? result_type(1) - u
>>> : -u;
>>> return -std::log(u2) * lambda_inv;
>>>
>>> Generating the centered uniform distribution seems redundant, you effectively map it to a
>>> uniform distribution on [0, 1) anyway with u2. So this also boils down to fixing the
>>> distribution on [0, 1), and centering doesn't give you anything for this particular use
>>> case. You throw away your increased resolution at `result_type(1) - u`.
>>
>> Correction, for u2 you effectively generate uniformly on (0, 1]. This improves the tail
>> distribution of the generated exponential_distribution compared to using
>> generate_canonical, but makes the distribution less accurate near 0, as it skips over a
>> lot of representable values.
>>
>> Honestly, neither technique is great in terms of accuracy, and it's probably possible to
>> implement exponential_distribution in a way that it can actually take any representable
>> value within the distribution. And the exponential distribution has density beyond
>> FLT_MAX, so theoretically inf is a valid result, but the probability of rolling above
>> FLT_MAX is usually beyond astronomically low, so I guess fixing that made sense.
>>
>>>
>>>>
>>>>
>>>> --
>>>> Std-Proposals mailing list
>>>> Std-Proposals_at_[hidden]
>>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>>>
>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>

Received on 2025-12-06 16:35:33