Changeset 1a617ac in mainline


Ignore:
Timestamp:
2018-07-05T21:41:22Z (6 years ago)
Author:
Dzejrou <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
2fe861d
Parents:
4654b29
git-author:
Dzejrou <dzejrou@…> (2018-05-02 15:43:15)
git-committer:
Dzejrou <dzejrou@…> (2018-07-05 21:41:22)
Message:

cpp: added linear_congruential_engine

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/impl/random.hpp

    r4654b29 r1a617ac  
    3333#include <ctime>
    3434#include <initializer_list>
     35#include <internal/builtins.hpp>
    3536#include <limits>
    3637#include <type_traits>
     
    4344 *       they should seek the mentioned standard section near
    4445 *       the declaration of these variables.
     46 * Note: There will be a lot of mathematical expressions in this header.
     47 *       All of these are taken directly from the standard's requirements
     48 *       and as such won't be commented here, check the appropriate
     49 *       sections if you need explanation of these forumulae.
    4550 */
    4651
     
    7580    class linear_congruential_engine
    7681    {
     82        static_assert(m == 0 || (a < m && c < m));
     83
    7784        public:
    7885            using result_type = UIntType;
     
    94101            static constexpr result_type default_seed = 1U;
    95102
    96             explicit linear_congruential_engine(result_type s = default_seed);
     103            explicit linear_congruential_engine(result_type s = default_seed)
     104                : state_{}
     105            {
     106                seed(s);
     107            }
     108
     109            linear_congruential_engine(const linear_congruential_engine& other)
     110                : state_{other.state_}
     111            { /* DUMMY BODY */ }
    97112
    98113            template<class Seq>
    99114            explicit linear_congruential_engine(
    100115                enable_if_t<aux::is_seed_sequence_v<Seq, result_type>, Seq&> q
    101             );
    102 
    103             void seed(result_type s = default_seed);
     116            )
     117                : state_{}
     118            {
     119                size_t k = static_cast<size_t>(aux::ceil(aux::log2(modulus_) / 32));
     120                auto arr = new result_type[k + 3];
     121
     122                q.generate(arr, arr + k + 3);
     123
     124                result_type s{};
     125                for (size_t j = 0; j < k; ++j)
     126                    s += a[j + 3] * aux::pow2(32U * j);
     127                s = s % modulus_;
     128
     129                seed(s);
     130            }
     131
     132            void seed(result_type s = default_seed)
     133            {
     134                if (c % modulus_ == 0 && s == 0)
     135                    state_ = 0;
     136                else
     137                    state_ = s;
     138            }
    104139
    105140            template<class Seq>
     
    108143            );
    109144
    110             result_type operator()();
    111 
    112             void discard(unsigned long long z);
     145            result_type operator()()
     146            {
     147                return generate_();
     148            }
     149
     150            void discard(unsigned long long z)
     151            {
     152                for (unsigned long long i = 0ULL; i < z; ++i)
     153                    transition_();
     154            }
     155
     156            bool operator==(const linear_congruential_engine& rhs) const
     157            {
     158                return state_ = rhs.state_;
     159            }
     160
     161            bool operator!=(const linear_congruential_engine& rhs) const
     162            {
     163                return !(*this == rhs);
     164            }
     165
     166            template<class Char, class Traits>
     167            basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os) const
     168            {
     169                auto flags = os.flags();
     170                os.flags(ios_base::dec | ios_base::left);
     171
     172                os << state_;
     173
     174                os.flags(flags);
     175                return os;
     176            }
     177
     178            template<class Char, class Traits>
     179            basic_istream<Char, Traits>& operator>>(basic_istream<Char, Traits>& is) const
     180            {
     181                auto flags = is.flags();
     182                is.flags(ios_base::dec);
     183
     184                result_type tmp{};
     185                if (is >> tmp)
     186                    state_ = tmp;
     187                else
     188                    is.setstate(ios::failbit);
     189
     190                is.flags(flags);
     191                return is;
     192            }
     193
     194        private:
     195            result_type state_;
     196
     197            static constexpr result_type modulus_ =
     198                (m == 0) ? (numeric_limits<result_type>::max() + 1) : m;
     199
     200            void transition_()
     201            {
     202                state_ = (a * state_ + c) % modulus_;
     203            }
     204
     205            result_type generate_()
     206            {
     207                transition_();
     208
     209                return state_;
     210            }
    113211    };
    114212
Note: See TracChangeset for help on using the changeset viewer.