Fix random_device to work with COW strings again
Instead of duplicating the initialization functions that take string, add a new member taking a raw pointer that can be used to convert the constructor token from the old string to the new. Also fix "mt19337" typos in a testcase. * include/bits/random.h (random_device::_M_init(const char*, size_t)): Add new private member function. * src/c++11/cow-string-inst.cc (random_device::_M_init(const string&)) (random_device::_M_init_pretr1(const string&)): Call new private member with string data. * src/c++11/random.cc (random_device::_M_init(const char*, size_t)): Define. * testsuite/26_numerics/random/random_device/cons/default-cow.cc: New test using COW strings. * testsuite/26_numerics/random/random_device/cons/default.cc: Generate a value from the device. * testsuite/26_numerics/random/random_device/cons/token.cc: Likewise. Fix typo in token string. From-SVN: r271805
This commit is contained in:
parent
decc53df4e
commit
aeedf07705
|
@ -1,3 +1,19 @@
|
|||
2019-05-31 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/random.h (random_device::_M_init(const char*, size_t)):
|
||||
Add new private member function.
|
||||
* src/c++11/cow-string-inst.cc (random_device::_M_init(const string&))
|
||||
(random_device::_M_init_pretr1(const string&)): Call new private
|
||||
member with string data.
|
||||
* src/c++11/random.cc (random_device::_M_init(const char*, size_t)):
|
||||
Define.
|
||||
* testsuite/26_numerics/random/random_device/cons/default-cow.cc: New
|
||||
test using COW strings.
|
||||
* testsuite/26_numerics/random/random_device/cons/default.cc: Generate
|
||||
a value from the device.
|
||||
* testsuite/26_numerics/random/random_device/cons/token.cc: Likewise.
|
||||
Fix typo in token string.
|
||||
|
||||
2019-05-30 Nina Dinka Ranns <dinka.ranns@gmail.com>
|
||||
|
||||
LWG2788 basic_string spurious use of a default constructible allocator
|
||||
|
|
|
@ -1648,6 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
result_type _M_getval_pretr1();
|
||||
double _M_getentropy() const noexcept;
|
||||
|
||||
void _M_init(const char*, size_t); // not exported from the shared library
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
|
|
|
@ -35,61 +35,15 @@
|
|||
|
||||
#ifdef _GLIBCXX_USE_C99_STDINT_TR1
|
||||
#include <random>
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
# include <cpuid.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
void
|
||||
random_device::_M_init(const std::string& token)
|
||||
{
|
||||
const char *fname = token.c_str();
|
||||
|
||||
if (token == "default")
|
||||
{
|
||||
#if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
// Check availability of cpuid and, for now at least, also the
|
||||
// CPU signature for Intel's
|
||||
if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_INTEL_ebx)
|
||||
{
|
||||
__cpuid(1, eax, ebx, ecx, edx);
|
||||
if (ecx & bit_RDRND)
|
||||
{
|
||||
_M_file = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fname = "/dev/urandom";
|
||||
}
|
||||
else if (token != "/dev/urandom" && token != "/dev/random")
|
||||
fail:
|
||||
std::__throw_runtime_error(__N("random_device::"
|
||||
"random_device(const std::string&)"));
|
||||
|
||||
_M_file = static_cast<void*>(std::fopen(fname, "rb"));
|
||||
if (!_M_file)
|
||||
goto fail;
|
||||
}
|
||||
{ _M_init(token.c_str(), token.length()); }
|
||||
|
||||
void
|
||||
random_device::_M_init_pretr1(const std::string& token)
|
||||
{
|
||||
unsigned long __seed = 5489UL;
|
||||
if (token != "mt19937")
|
||||
{
|
||||
const char* __nptr = token.c_str();
|
||||
char* __endptr;
|
||||
__seed = std::strtoul(__nptr, &__endptr, 0);
|
||||
if (*__nptr == '\0' || *__endptr != '\0')
|
||||
std::__throw_runtime_error(__N("random_device::random_device"
|
||||
"(const std::string&)"));
|
||||
}
|
||||
_M_mt.seed(__seed);
|
||||
}
|
||||
{ _M_init(token.c_str(), token.length()); }
|
||||
} // namespace
|
||||
#endif
|
||||
|
|
|
@ -293,6 +293,18 @@ namespace std _GLIBCXX_VISIBILITY(default)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Called by old ABI version of random_device::_M_init(const std::string&).
|
||||
void
|
||||
random_device::_M_init(const char* s, size_t len)
|
||||
{
|
||||
const std::string token(s, len);
|
||||
#ifdef USE_MT19937
|
||||
_M_init_pretr1(token);
|
||||
#else
|
||||
_M_init(token);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
random_device::_M_fini()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// { dg-options "-D_GLIBCXX_USE_CXX11_ABI=0" }
|
||||
// { dg-do run { target c++11 } }
|
||||
// { dg-require-effective-target random_device }
|
||||
// { dg-require-cstdint "" }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// C++11 26.5.6 class random_device [rand.device]
|
||||
|
||||
#include <random>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
std::random_device x;
|
||||
auto n [[gnu::unused]] = x();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
}
|
|
@ -21,8 +21,7 @@
|
|||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// 26.4.6 class random_device [rand.device]
|
||||
// 26.4.2.2 Concept RandomNumberEngine [rand.concept.eng]
|
||||
// C++11 26.5.6 class random_device [rand.device]
|
||||
|
||||
#include <random>
|
||||
#include <testsuite_hooks.h>
|
||||
|
@ -32,8 +31,11 @@ test01()
|
|||
{
|
||||
std::random_device x;
|
||||
|
||||
VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() );
|
||||
VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() );
|
||||
using result_type = std::random_device::result_type;
|
||||
VERIFY( x.min() == std::numeric_limits<result_type>::min() );
|
||||
VERIFY( x.max() == std::numeric_limits<result_type>::max() );
|
||||
|
||||
result_type n [[gnu::unused]] = x();
|
||||
}
|
||||
|
||||
int main()
|
||||
|
|
|
@ -30,10 +30,9 @@ void
|
|||
test01()
|
||||
{
|
||||
std::random_device x("default");
|
||||
|
||||
VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() );
|
||||
VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() );
|
||||
|
||||
using result_type = std::random_device::result_type;
|
||||
VERIFY( x.min() == std::numeric_limits<result_type>::min() );
|
||||
VERIFY( x.max() == std::numeric_limits<result_type>::max() );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -42,6 +41,7 @@ test02()
|
|||
#ifdef _GLIBCXX_USE_DEV_RANDOM
|
||||
std::random_device x1("/dev/urandom");
|
||||
std::random_device x2("/dev/random");
|
||||
VERIFY( x1() != x2() );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ test03()
|
|||
{
|
||||
// At least one of these tokens should be valid.
|
||||
const std::string tokens[] = {
|
||||
"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19337"
|
||||
"rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937"
|
||||
};
|
||||
int count = 0;
|
||||
for (const std::string& token : tokens)
|
||||
|
@ -71,21 +71,25 @@ void
|
|||
test04()
|
||||
{
|
||||
bool can_use_mt19937 = true;
|
||||
std::random_device::result_type xval;
|
||||
try
|
||||
{
|
||||
std::random_device x("mt19937");
|
||||
xval = x();
|
||||
}
|
||||
catch (const std::runtime_error&)
|
||||
{
|
||||
can_use_mt19937 = false;
|
||||
}
|
||||
|
||||
// If "mt19337" is a valid token then numeric seeds should be too.
|
||||
// If "mt19937" is a valid token then numeric seeds should be too.
|
||||
if (can_use_mt19937)
|
||||
{
|
||||
std::random_device x1("0");
|
||||
std::random_device x2("1234");
|
||||
std::random_device x3("0xc0fefe");
|
||||
VERIFY( xval != x1() );
|
||||
VERIFY( x2() != x3() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue