diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index 35c2df3d..bd028f6e 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -185,6 +185,7 @@ class database_api_impl : public std::enable_shared_from_this gpos_info get_gpos_info(const account_id_type account) const; // rng + vector get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const; int64_t get_random_number(uint64_t bound) const; //private: @@ -2312,14 +2313,51 @@ graphene::app::gpos_info database_api_impl::get_gpos_info(const account_id_type // // ////////////////////////////////////////////////////////////////////// +vector database_api::get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const +{ + return my->get_random_number_ex(minimum, maximum, selections, duplicates); +} + +vector database_api_impl::get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const +{ + FC_ASSERT( selections <= 100000 ); + if (duplicates == false) { + FC_ASSERT( maximum - minimum >= selections ); + } + + vector v; + v.reserve(selections); + + if (duplicates) { + for (uint64_t i = 0; i < selections; i++) { + int64_t rnd = _db.get_random_bits(maximum - minimum) + minimum; + v.push_back(rnd); + } + } else { + vector tmpv; + tmpv.reserve(selections); + for (uint64_t i = minimum; i < maximum; i++) { + tmpv.push_back(i); + } + + while (tmpv.size() > 0) { + uint64_t idx = _db.get_random_bits(tmpv.size()); + v.push_back(tmpv.at(idx)); + tmpv.erase(tmpv.begin() + idx); + } + } + + return v; +} + int64_t database_api::get_random_number(uint64_t bound) const { return my->get_random_number(bound); } int64_t database_api_impl::get_random_number(uint64_t bound) const { - int64_t result = _db.get_random_bits(bound); - return result; + vector v = get_random_number_ex(0, bound, 1, false); + return v.at(0); } ////////////////////////////////////////////////////////////////////// diff --git a/libraries/app/include/graphene/app/database_api.hpp b/libraries/app/include/graphene/app/database_api.hpp index da959d9b..405bbc58 100644 --- a/libraries/app/include/graphene/app/database_api.hpp +++ b/libraries/app/include/graphene/app/database_api.hpp @@ -712,6 +712,16 @@ class database_api ///////////////////////////// // Random number generator // ///////////////////////////// + /** + * @brief Returns the random number + * @param minimum Lower bound of segment containing random number + * @param maximum Upper bound of segment containing random number + * @param selections Number of random numbers to return + * @param duplicates Allow duplicated numbers + * @return Vector containing random numbers from segment [minimum, maximum) + */ + vector get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const; + /** * @brief Returns the random number * @param bound Upper bound of segment containing random number @@ -858,5 +868,6 @@ FC_API(graphene::app::database_api, (get_gpos_info) // rngs + (get_random_number_ex) (get_random_number) )