#ifndef RANDOM_2019_09_24_H_ #define RANDOM_2019_09_24_H_ #include #include #include #include namespace al { namespace crypto { namespace random { template class random_device { public: using result_type = ResultType; static_assert( (std::numeric_limits::is_integer == true) && (std::numeric_limits::is_signed == false) && (std::numeric_limits::digits <= 512), "Error: At the moment random_device is limited to unsigned integral result_type having 512 bits or fewer."); random_device() { } random_device& operator=(const random_device&) = delete; result_type operator()() { return get_advance(); } static result_type (min)() { return (std::numeric_limits::min)(); } static result_type (max)() { return (std::numeric_limits::max)(); } double entropy() const { return 2.0; } private: using clock_type = std::chrono::high_resolution_clock; static const std::uintmax_t& initial_now() { // Obtain an initial value of std::chrono::high_resolution_clock::now(). static const std::uintmax_t local_now = static_cast(std::chrono::duration_cast (clock_type::now().time_since_epoch()).count()); return local_now; } static result_type get_advance() { // Obtain an initial value of std::chrono::high_resolution_clock::now(). std::uintmax_t current_now; do { // Wait for std::chrono::high_resolution_clock::now() // to differ from the initialization value. current_now = static_cast(std::chrono::duration_cast (clock_type::now().time_since_epoch()).count()); } while(current_now == initial_now()); // Perform a logical xor of current_now with the maximum value of its type. current_now ^= (std::numeric_limits::max)(); // Extract the data bytes of current now into an array... std::array::digits / 8U> current_now_data; for(std::size_t i = 0U; i < current_now_data.size(); ++i) { current_now_data[i] = std::uint8_t(current_now >> (i * 8U)); } // ... and... Finally, run a SHA512 hash over the data bytes of current_now. using hash_type = al::crypto::stream::hash::hash_sha512; hash_type h; hash_type::result_type hash_result; h.hash_and_get_result(current_now_data.data(), current_now_data.size(), hash_result.data()); // Extract the required bytes from the hash result // in order to obtain the pseudo-random seed. result_type result(0U); for(std::size_t i = 0U; i < sizeof(result_type); ++i) { result |= result_type(result_type(hash_result[i]) << (i * 8U)); } // Return the pseudo-random seed. return result; } }; template class uniform_int_distribution { public: using result_type = IntType; struct param_type { public: param_type(const result_type& a = (std::numeric_limits::min)(), const result_type& b = (std::numeric_limits::max)()) : param_a(a), param_b(b) { } ~param_type() = default; param_type(const param_type& other_params) : param_a(other_params.param_a), param_b(other_params.param_b) { } param_type& operator=(const param_type& other_params) { if(this != &other_params) { param_a = other_params.param_a; param_b = other_params.param_b; } return *this; } const result_type& get_a() const { return param_a; } const result_type& get_b() const { return param_b; } void set_a(const result_type& a) { param_a = a; } void set_b(const result_type& b) { param_b = b; } private: result_type param_a; result_type param_b; }; uniform_int_distribution() : my_params() { } explicit uniform_int_distribution(const result_type& a, const result_type& b = (std::numeric_limits::max)()) : my_params(param_type(a, b)) { } explicit uniform_int_distribution(const param_type& other_params) : my_params(other_params) { } uniform_int_distribution(const uniform_int_distribution& other_distribution) : my_params(other_distribution.my_params) { } ~uniform_int_distribution() = default; uniform_int_distribution& operator=(const uniform_int_distribution& other_distribution) { if(this != &other_distribution) { my_params = other_distribution.my_params; } return *this; } void param(const param_type& new_params) { my_params = new_params; } const param_type& param() const { return my_params; } const result_type a() const { return param().get_a(); } const result_type b() const { return param().get_b(); } template result_type operator()(GeneratorType& generator) { return generate(generator, my_params); } template result_type operator()(GeneratorType& input_generator, const param_type& input_params) { return generate(input_generator, input_params); } private: param_type my_params; template result_type generate(GeneratorType& input_generator, const param_type& input_params) { result_type result = input_generator(); if( (input_params.get_a() != (std::numeric_limits::min)()) || (input_params.get_b() != (std::numeric_limits::max)())) { result_type range(input_params.get_b() - input_params.get_a()); ++range; result %= range; result += input_params.get_a(); } return result; } }; template bool operator==(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { return ( (lhs.params().get_a() == rhs.params().get_a()) && (lhs.params().get_b() == rhs.params().get_b())); } template bool operator!=(const uniform_int_distribution& lhs, const uniform_int_distribution& rhs) { return ( (lhs.params().get_a() != rhs.params().get_a()) || (lhs.params().get_b() != rhs.params().get_b())); } } } } // al::crpyto::random #include #include #include #endif // RANDOM_DEVICE_2019_09_24_H_