rand/rdrand: add rdrand generator

This commit is contained in:
Danny Robson 2019-06-19 12:02:50 +10:00
parent 3a83851e90
commit f86989bc67
4 changed files with 87 additions and 0 deletions

View File

@ -440,6 +440,8 @@ list (
rand/mwc64x.hpp rand/mwc64x.hpp
rand/pcg.cpp rand/pcg.cpp
rand/pcg.hpp rand/pcg.hpp
rand/rdrand.cpp
rand/rdrand.hpp
rand/system.hpp rand/system.hpp
random.cpp random.cpp
random.hpp random.hpp

44
rand/rdrand.cpp Normal file
View File

@ -0,0 +1,44 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#include "rdrand.hpp"
using cruft::rand::rdrand;
///////////////////////////////////////////////////////////////////////////////
rdrand::rdrand ()
{ ; }
//---------------------------------------------------------------------------------------
rdrand::rdrand (std::string const &)
: rdrand ()
{ ; }
///////////////////////////////////////////////////////////////////////////////
rdrand::result_type
rdrand::operator() ()
{
uint64_t res;
char success;
__asm__ __volatile__ (
"rdrand %0;"
"setc %1;"
: "=r" (res)
, "=qm" (success)
);
if (!__builtin_expect(success, 1))
throw std::runtime_error ("no value available for rdrand");
return res;
}

40
rand/rdrand.hpp Normal file
View File

@ -0,0 +1,40 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2019 Danny Robson <danny@nerdcruft.net>
*/
#pragma once
#include "../posix/fd.hpp"
namespace cruft::rand {
/// Models std::random_device and is suitable as a drop-in replacement.
///
/// This implementation assumes that the CPU supports the `rdrand`
/// instruction, and does not check that this is the case.
///
/// It is safe to instantiatate the object even if the instructions are
/// not supported, but it is the users responsibility to prevent calls to
/// the object if this is not the case.
class rdrand {
public:
using result_type = unsigned;
rdrand ();
rdrand (std::string const&);
rdrand (rdrand const &) = delete;
rdrand& operator= (rdrand const&) = delete;
result_type operator() (void);
double entropy (void) const noexcept;
static constexpr result_type min (void) { return std::numeric_limits<result_type>::min (); }
static constexpr result_type max (void) { return std::numeric_limits<result_type>::max (); }
};
}

View File

@ -55,6 +55,7 @@ main (int,char**)
test_buckets<cruft::rand::mwc64x> (tap, 0x1234u); test_buckets<cruft::rand::mwc64x> (tap, 0x1234u);
test_buckets<cruft::rand::pcg_xsh_rr<>> (tap, 0x1234u); test_buckets<cruft::rand::pcg_xsh_rr<>> (tap, 0x1234u);
test_buckets<cruft::rand::system> (tap); test_buckets<cruft::rand::system> (tap);
test_buckets<cruft::rand::rdrand> (tap);
return tap.status (); return tap.status ();
} }