diff --git a/sprout/iterator/reverse_iterator.hpp b/sprout/iterator/reverse_iterator.hpp index 1f750596..5cf6a6c9 100644 --- a/sprout/iterator/reverse_iterator.hpp +++ b/sprout/iterator/reverse_iterator.hpp @@ -62,10 +62,10 @@ namespace sprout { reverse_iterator& operator++() { --current; --deref_tmp; - return this; + return *this; } reverse_iterator operator++(int) { - reverse_iterator result(this); + reverse_iterator result(*this); --current; --deref_tmp; return result; @@ -73,10 +73,10 @@ namespace sprout { reverse_iterator& operator--() { ++current; ++deref_tmp; - return this; + return *this; } reverse_iterator operator--(int) { - reverse_iterator temp(this); + reverse_iterator temp(*this); ++current; ++deref_tmp; return temp; diff --git a/sprout/random.hpp b/sprout/random.hpp index 5dd09c66..db5fe094 100644 --- a/sprout/random.hpp +++ b/sprout/random.hpp @@ -2,11 +2,12 @@ #define SPROUT_RANDOM_HPP #include -#include #include #include #include #include +#include +#include #endif // #ifndef SPROUT_RANDOM_HPP diff --git a/sprout/random/random_iterator.hpp b/sprout/random/random_iterator.hpp new file mode 100644 index 00000000..18b80f22 --- /dev/null +++ b/sprout/random/random_iterator.hpp @@ -0,0 +1,280 @@ +#ifndef SPROUT_RANDOM_RANDOM_ITERATOR_HPP +#define SPROUT_RANDOM_RANDOM_ITERATOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace random { + // + // random_iterator + // + template + class random_iterator; + + template + class random_iterator< + Engine, + Distribution, + typename std::enable_if::value>::type + > + : public std::iterator< + typename std::iterator_traits >::iterator_category, + typename std::iterator_traits >::value_type, + typename std::iterator_traits >::difference_type, + typename std::iterator_traits >::pointer, + typename std::iterator_traits >::reference + > + { + public: + typedef sprout::random::random_result random_result_type; + typedef typename random_result_type::engine_type engine_type; + typedef typename random_result_type::distribution_type distribution_type; + typedef typename random_result_type::result_type result_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + private: + random_result_type random_; + difference_type count_; + public: + SPROUT_CONSTEXPR random_iterator() + : random_() + , count_() + {} + SPROUT_CONSTEXPR random_iterator( + engine_type const& engine, + distribution_type const& distribution, + difference_type count = -1 + ) + : random_(distribution(engine)) + , count_(count) + {} + SPROUT_CONSTEXPR explicit random_iterator( + random_result_type const& random, + difference_type count = -1 + ) + : random_(random) + , count_(count) + {} + SPROUT_CONSTEXPR random_iterator operator()() const { + return count_ != 0 + ? random_iterator(random_(), count_ > 0 ? count_ - 1 : count_) + : throw "assert(count_ != 0)" + ; + } + random_result_type& random_result() { + return random_; + } + SPROUT_CONSTEXPR random_result_type const& random_result() const { + return random_; + } + result_type& result() { + return random_.result(); + } + SPROUT_CONSTEXPR result_type const& result() const { + return random_.result(); + } + engine_type& engine() { + return random_.engine(); + } + SPROUT_CONSTEXPR engine_type const& engine() const { + return random_.engine(); + } + distribution_type& distribution() { + return random_.distribution(); + } + SPROUT_CONSTEXPR distribution_type const& distribution() const { + return random_.distribution(); + } + SPROUT_CONSTEXPR result_type min() const { + return random_.min(); + } + SPROUT_CONSTEXPR result_type max() const { + return random_.max(); + } + SPROUT_CONSTEXPR result_type count() const { + return count_; + } + void swap(random_iterator& other) { + using std::swap; + swap(random_, other.random_); + swap(count_, other.count_); + } + friend SPROUT_CONSTEXPR bool operator==(random_iterator const& lhs, random_iterator const& rhs) { + return lhs.count_ == rhs.count_ && (lhs.count_ == 0 || lhs.random_ == rhs.random_); + } + friend SPROUT_CONSTEXPR bool operator!=(random_iterator const& lhs, random_iterator const& rhs) { + return !(lhs == rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return count_ != 0 + ? random_.result() + : throw "assert(count_ != 0)" + ; + } + SPROUT_CONSTEXPR pointer operator->() const { + return count_ > 0 + ? &random_.result() + : throw "assert(count_ != 0)" + ; + } + random_iterator& operator++() { + random_iterator temp((*this)()); + temp.swap(*this); + return *this; + } + random_iterator operator++(int) { + random_iterator result(*this); + ++*this; + return result; + } + }; + template + class random_iterator< + Engine, + Distribution, + typename std::enable_if::value>::type + > + : public std::iterator< + typename std::iterator_traits >::iterator_category, + typename std::iterator_traits >::value_type, + typename std::iterator_traits >::difference_type, + typename std::iterator_traits >::pointer, + typename std::iterator_traits >::reference + > + { + public: + typedef sprout::random::random_result random_result_type; + typedef typename random_result_type::engine_type engine_type; + typedef typename random_result_type::result_type result_type; + typedef typename std::iterator_traits::iterator_category iterator_category; + typedef typename std::iterator_traits::value_type value_type; + typedef typename std::iterator_traits::difference_type difference_type; + typedef typename std::iterator_traits::pointer pointer; + typedef typename std::iterator_traits::reference reference; + private: + random_result_type random_; + difference_type count_; + public: + SPROUT_CONSTEXPR random_iterator() + : random_() + , count_() + {} + SPROUT_CONSTEXPR random_iterator( + engine_type const& engine, + difference_type count = -1 + ) + : random_(engine()) + , count_(count) + {} + SPROUT_CONSTEXPR explicit random_iterator( + random_result_type const& random, + difference_type count = -1 + ) + : random_(random) + , count_(count) + {} + SPROUT_CONSTEXPR random_iterator operator()() const { + return count_ != 0 + ? random_iterator(random_(), count_ > 0 ? count_ - 1 : count_) + : throw "assert(count_ != 0)" + ; + } + random_result_type& random_result() { + return random_; + } + SPROUT_CONSTEXPR random_result_type const& random_result() const { + return random_; + } + result_type& result() { + return random_.result(); + } + SPROUT_CONSTEXPR result_type const& result() const { + return random_.result(); + } + engine_type& engine() { + return random_.engine(); + } + SPROUT_CONSTEXPR engine_type const& engine() const { + return random_.engine(); + } + SPROUT_CONSTEXPR result_type min() const { + return random_.min(); + } + SPROUT_CONSTEXPR result_type max() const { + return random_.max(); + } + SPROUT_CONSTEXPR result_type count() const { + return count_; + } + void swap(random_iterator& other) { + using std::swap; + swap(random_, other.random_); + swap(count_, other.count_); + } + friend SPROUT_CONSTEXPR bool operator==(random_iterator const& lhs, random_iterator const& rhs) { + return lhs.count_ == rhs.count_ && (lhs.count_ == 0 || lhs.random_ == rhs.random_); + } + friend SPROUT_CONSTEXPR bool operator!=(random_iterator const& lhs, random_iterator const& rhs) { + return !(lhs == rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return count_ != 0 + ? random_.result() + : throw "assert(count_ != 0)" + ; + } + SPROUT_CONSTEXPR pointer operator->() const { + return count_ > 0 + ? &random_.result() + : throw "assert(count_ != 0)" + ; + } + random_iterator& operator++() { + random_iterator temp((*this)()); + temp.swap(*this); + return *this; + } + random_iterator operator++(int) { + random_iterator result(*this); + ++*this; + return result; + } + }; + // + // swap + // + template + void swap( + sprout::random::random_iterator& lhs, + sprout::random::random_iterator& rhs + ) + { + lhs.swap(rhs); + } + + // + // next + // + template + SPROUT_CONSTEXPR sprout::random::random_iterator next( + sprout::random::random_iterator const& it + ) + { + return it(); + } + } // namespace random + + using sprout::random::random_iterator; +} // namespace sprout + +#endif // #ifndef SPROUT_RANDOM_RANDOM_ITERATOR_HPP diff --git a/sprout/random/random_result.hpp b/sprout/random/random_result.hpp index 99f5e730..ddd4ea9c 100644 --- a/sprout/random/random_result.hpp +++ b/sprout/random/random_result.hpp @@ -1,8 +1,12 @@ #ifndef SPROUT_RANDOM_RANDOM_RESULT_HPP #define SPROUT_RANDOM_RANDOM_RESULT_HPP +#include +#include +#include #include #include +#include namespace sprout { namespace random { @@ -17,11 +21,33 @@ namespace sprout { Engine, Distribution, typename std::enable_if::value>::type - > { + > + : public std::iterator< + std::forward_iterator_tag, + typename Distribution::result_type, + std::ptrdiff_t, + typename Distribution::result_type const*, + typename Distribution::result_type const& + > + { public: typedef Engine engine_type; typedef Distribution distribution_type; typedef typename distribution_type::result_type result_type; + private: + typedef std::iterator< + std::forward_iterator_tag, + result_type, + std::ptrdiff_t, + result_type const*, + result_type const& + > base_type; + public: + typedef typename base_type::iterator_category iterator_category; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::reference reference; private: result_type result_; engine_type engine_; @@ -39,9 +65,6 @@ namespace sprout { SPROUT_CONSTEXPR operator result_type() const { return result_; } - SPROUT_CONSTEXPR result_type operator*() const { - return result_; - } SPROUT_CONSTEXPR random_result operator()() const { return distribution_(engine_); } @@ -69,16 +92,69 @@ namespace sprout { SPROUT_CONSTEXPR result_type max() const { return distribution_.max(); } + void swap(random_result& other) { + using std::swap; + swap(result_, other.result_); + swap(engine_, other.engine_); + swap(distribution_, other.distribution_); + } + friend SPROUT_CONSTEXPR bool operator==(random_result const& lhs, random_result const& rhs) { + return lhs.result_ == rhs.result_ + && lhs.engine_ == rhs.engine_ + && lhs.distribution_ == rhs.distribution_ + ; + } + friend SPROUT_CONSTEXPR bool operator!=(random_result const& lhs, random_result const& rhs) { + return !(lhs == rhs); + } + SPROUT_CONSTEXPR reference operator*() const { + return result_; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &result_; + } + random_result& operator++() { + random_result temp((*this)()); + temp.swap(*this); + return *this; + } + random_result operator++(int) { + random_result result(*this); + ++*this; + return result; + } }; template class random_result< Engine, Distribution, typename std::enable_if::value>::type - > { + > + : public std::iterator< + std::forward_iterator_tag, + typename Engine::result_type, + std::ptrdiff_t, + typename Engine::result_type const*, + typename Engine::result_type const& + > + { public: typedef Engine engine_type; typedef typename engine_type::result_type result_type; + private: + typedef std::iterator< + std::forward_iterator_tag, + result_type, + std::ptrdiff_t, + result_type const*, + result_type const& + > base_type; + public: + typedef typename base_type::iterator_category iterator_category; + typedef typename base_type::value_type value_type; + typedef typename base_type::difference_type difference_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::reference reference; private: result_type result_; engine_type engine_; @@ -93,9 +169,6 @@ namespace sprout { SPROUT_CONSTEXPR operator result_type() const { return result_; } - SPROUT_CONSTEXPR result_type operator*() const { - return result_; - } SPROUT_CONSTEXPR random_result operator()() const { return engine_(); } @@ -117,7 +190,59 @@ namespace sprout { SPROUT_CONSTEXPR result_type max() const { return engine_.max(); } + friend SPROUT_CONSTEXPR bool operator==(random_result const& lhs, random_result const& rhs) { + return lhs.result_ == rhs.result_ + && lhs.engine_ == rhs.engine_ + ; + } + friend SPROUT_CONSTEXPR bool operator!=(random_result const& lhs, random_result const& rhs) { + return !(lhs == rhs); + } + void swap(random_result& other) { + using std::swap; + swap(result_, other.result_); + swap(engine_, other.engine_); + } + SPROUT_CONSTEXPR reference operator*() const { + return result_; + } + SPROUT_CONSTEXPR pointer operator->() const { + return &result_; + } + random_result& operator++() { + random_result temp((*this)()); + temp.swap(*this); + return *this; + } + random_result operator++(int) { + random_result result(*this); + random_result temp((*this)()); + temp.swap(*this); + return result; + } }; + // + // swap + // + template + void swap( + sprout::random::random_result& lhs, + sprout::random::random_result& rhs + ) + { + lhs.swap(rhs); + } + + // + // next + // + template + SPROUT_CONSTEXPR sprout::random::random_result next( + sprout::random::random_result const& it + ) + { + return it(); + } } // namespace random using sprout::random::random_result;