#ifndef SPROUT_ITERATOR_SINUSOID_ITERATOR_HPP #define SPROUT_ITERATOR_SINUSOID_ITERATOR_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { // // sinusoid_iterator // template class sinusoid_iterator : public std::iterator< std::random_access_iterator_tag, Value, std::ptrdiff_t, Value*, Value > { public: typedef std::random_access_iterator_tag iterator_category; typedef Value value_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type reference; private: difference_type index_; value_type frequency_; value_type amplitude_; value_type phase_; value_type d_; private: explicit SPROUT_CONSTEXPR sinusoid_iterator(sinusoid_iterator const& other, difference_type index) : index_(index) , frequency_(other.frequency_) , amplitude_(other.amplitude_) , phase_(other.phase_) , d_(other.d_) {} public: SPROUT_CONSTEXPR sinusoid_iterator() : index_() , frequency_(1) , amplitude_(1) , phase_(0) , d_(value_type(2) * sprout::math::pi()) {} sinusoid_iterator(sinusoid_iterator const&) = default; explicit SPROUT_CONSTEXPR sinusoid_iterator( difference_type index, value_type const& frequency = 1, value_type const& amplitude = 1, value_type const& phase = 0 ) : index_(index) , frequency_(frequency) , amplitude_(amplitude) , phase_(phase) , d_(value_type(2) * sprout::math::pi() * frequency) {} template SPROUT_CONSTEXPR sinusoid_iterator(sinusoid_iterator const& it) : index_(it.index_) , frequency_(it.frequency_) , amplitude_(it.amplitude_) , phase_(it.phase_) , d_(it.d_) {} template sinusoid_iterator& operator=(sinusoid_iterator const& it) { sinusoid_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR difference_type index() const { return index_; } SPROUT_CONSTEXPR value_type const& frequency() const { return frequency_; } SPROUT_CONSTEXPR value_type const& amplitude() const { return amplitude_; } SPROUT_CONSTEXPR value_type const& phase() const { return phase_; } SPROUT_CONSTEXPR reference operator*() const { using std::sin; return amplitude_ * sin(d_ * value_type(index_) + phase_); } SPROUT_CONSTEXPR pointer operator->() const { return &operator*()(); } sinusoid_iterator& operator++() { ++index_; return *this; } sinusoid_iterator operator++(int) { sinusoid_iterator result(*this); ++index_; return result; } sinusoid_iterator& operator--() { --index_; return *this; } sinusoid_iterator operator--(int) { sinusoid_iterator temp(*this); --index_; return temp; } SPROUT_CONSTEXPR sinusoid_iterator operator+(difference_type n) const { return sinusoid_iterator(*this, index_ + n); } SPROUT_CONSTEXPR sinusoid_iterator operator-(difference_type n) const { return sinusoid_iterator(*this, index_ - n); } sinusoid_iterator& operator+=(difference_type n) { sinusoid_iterator temp(*this, index_ + n); temp.swap(*this); return *this; } sinusoid_iterator& operator-=(difference_type n) { sinusoid_iterator temp(*this, index_ - n); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { using std::sin; return amplitude_ * sin(d_ * value_type(index_ + n) + phase_); } SPROUT_CONSTEXPR sinusoid_iterator next() const { return sinusoid_iterator(*this, index_ + 1); } SPROUT_CONSTEXPR sinusoid_iterator prev() const { return sinusoid_iterator(*this, index_ - 1); } void swap(sinusoid_iterator& other) { using std::swap; swap(index_, other.index_); swap(frequency_, other.frequency_); swap(amplitude_, other.amplitude_); swap(phase_, other.phase_); swap(d_, other.d_); } }; template SPROUT_CONSTEXPR bool operator==( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return lhs.index() == rhs.index(); } template SPROUT_CONSTEXPR bool operator!=( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return !(lhs == rhs); } template SPROUT_CONSTEXPR bool operator<( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return lhs.index() < rhs.index(); } template SPROUT_CONSTEXPR bool operator>( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return rhs < lhs; } template SPROUT_CONSTEXPR bool operator<=( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return !(rhs < lhs); } template SPROUT_CONSTEXPR bool operator>=( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return !(lhs < rhs); } template SPROUT_CONSTEXPR typename sprout::sinusoid_iterator::difference_type operator-( sprout::sinusoid_iterator const& lhs, sprout::sinusoid_iterator const& rhs ) { return lhs.index() - rhs.index(); } template SPROUT_CONSTEXPR sprout::sinusoid_iterator operator+( typename sprout::sinusoid_iterator::difference_type n, sprout::sinusoid_iterator const& it ) { return it + n; } // // swap // template void swap(sprout::sinusoid_iterator& lhs, sprout::sinusoid_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // next // template SPROUT_CONSTEXPR sprout::sinusoid_iterator next( sprout::sinusoid_iterator const& it ) { return it.next(); } template SPROUT_CONSTEXPR sprout::sinusoid_iterator next( sprout::sinusoid_iterator const& it, typename sprout::sinusoid_iterator::difference_type n ) { return it + n; } // // prev // template SPROUT_CONSTEXPR sprout::sinusoid_iterator prev( sprout::sinusoid_iterator const& it ) { return it.prev(); } template SPROUT_CONSTEXPR sprout::sinusoid_iterator prev( sprout::sinusoid_iterator const& it, typename sprout::sinusoid_iterator::difference_type n ) { return it - n; } // // distance // template SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type distance( sprout::sinusoid_iterator first, sprout::sinusoid_iterator last ) { return last - first; } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_SINUSOID_ITERATOR_HPP