Bug 63176 - std::generate_canonical<float, std::numeric_limits<float>::digits>() generates 1.0f
Summary: std::generate_canonical<float, std::numeric_limits<float>::digits>() generate...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 6.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-09-04 16:52 UTC by schwan
Modified: 2020-12-10 10:22 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-08-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description schwan 2014-09-04 16:52:43 UTC
std::generate_canonical can generate 1.0, which does not conform to the c++11 standard. On my box the following program yields "Bug!":

#include <iostream>
#include <limits>
#include <random>

int main()
{
    std::mt19937 rng;

    std::seed_seq sequence{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    rng.seed(sequence);
    rng.discard(12 * 629143 + 6);

    float random = std::generate_canonical<float,
                   std::numeric_limits<float>::digits>(rng);

    if (random == 1.0f)
    {
        std::cout << "Bug!\n";
    }

    return 0;
}

See also http://stackoverflow.com/questions/25668600/is-1-0-a-valid-random-number for a longer discussion and analysis of the problem.

I first noticed this on my system GCC,

gcc (Gentoo 4.7.3-r1 p1.4, pie-0.5.5) 4.7.3
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

but I can reproduce the same behavior with a recent GCC from git:

gcc (GCC) 5.0.0 20140830 (experimental)
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I used `c++ =std=c++11` to compile the program above.
Comment 1 Jonathan Wakely 2015-08-26 21:27:41 UTC
Author: redi
Date: Wed Aug 26 21:27:09 2015
New Revision: 227233

URL: https://gcc.gnu.org/viewcvs?rev=227233&root=gcc&view=rev
Log:
Ensure std::generate_canonical doesn't return 1.

2015-08-26  Edward Smith-Rowland  <3dw4rd@verizon.net>
	    Jonathan Wakely  <jwakely@redhat.com>

	PR libstdc++/64351
	PR libstdc++/63176
	* include/bits/random.tcc (generate_canonical): Loop until we get a
	result less than one.
	* testsuite/26_numerics/random/uniform_real_distribution/operators/
	64351.cc: New.

Added:
    trunk/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/64351.cc
Modified:
    trunk/libstdc++-v3/ChangeLog
    trunk/libstdc++-v3/include/bits/random.tcc
Comment 2 Jonathan Wakely 2015-08-26 21:28:04 UTC
Fixed on trunk.
Comment 3 TC 2015-10-10 03:45:38 UTC
This breaks the complexity requirement in [rand.util.canonical]/p3, though.
Comment 4 Jonathan Wakely 2015-10-12 10:28:35 UTC
Meh. Don't use generate_canonical<float> then.
Comment 5 Jonathan Wakely 2020-12-10 10:22:38 UTC
(In reply to TC from comment #3)
> This breaks the complexity requirement in [rand.util.canonical]/p3, though.

That did get fixed eventually, see PR 80137 / r246542