// (C) Copyright Gennadiy Rozental 2001. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // See http://www.boost.org/libs/test for the library home page. // ///@file ///Defines range generator // *************************************************************************** #ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER #define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER // Boost.Test #include #include #include // Boost #include #include #include // STL #include #include #include //____________________________________________________________________________// namespace boost { namespace unit_test { namespace data { namespace monomorphic { // ************************************************************************** // // ************** monomorphic::xrange_t ************** // // ************************************************************************** // /*!@brief Generator for the range sequences * * This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing * a range like sequence of numbers. */ template class xrange_t { public: typedef SampleType sample; xrange_t( SampleType const& begin_, StepType const& step_, data::size_t size_ ) : m_begin( begin_ ) , m_curr( begin_ ) , m_step( step_ ) , m_index( 0 ) , m_size( size_ ) {} // Generator interface data::size_t capacity() const { return m_size; } SampleType next() { if( m_index == m_size ) return m_curr; SampleType res = m_curr; m_curr += m_step; ++m_index; return res; } void reset() { m_curr = m_begin; m_index = 0; } private: // Data members SampleType m_begin; SampleType m_curr; StepType m_step; data::size_t m_index; data::size_t m_size; }; //____________________________________________________________________________// namespace ds_detail { template struct make_xrange { static StepType abs( StepType s, boost::true_type* ) { return s; } static StepType abs( StepType s, boost::false_type* ) { return std::abs(s); } typedef xrange_t range_gen; template static generated_by _( Params const& params ) { SampleType begin_val = params.has( data::begin ) ? params[data::begin] : SampleType(); optional end_val = params.has( data::end ) ? params[data::end] : optional(); StepType step_val = params.has( data::step ) ? params[data::step] : 1; BOOST_TEST_DS_ASSERT( step_val != 0, "Range step can't be zero" ); data::size_t size; if( !end_val.is_initialized() ) size = BOOST_TEST_DS_INFINITE_SIZE; else { BOOST_TEST_DS_ASSERT( (step_val < 0) ^ (begin_val < *end_val), "Invalid step direction" ); SampleType abs_distance = step_val < 0 ? begin_val - *end_val : *end_val-begin_val; StepType abs_step = make_xrange::abs(step_val, (typename boost::is_unsigned::type*)0 ); std::size_t s = static_cast(abs_distance/abs_step); if( static_cast(s*abs_step) < abs_distance ) s++; size = s; } return generated_by( range_gen( begin_val, step_val, size ) ); } }; } // namespace ds_detail } // namespace monomorphic //____________________________________________________________________________// //! Creates a range (sequence) dataset. //! //! The following overloads are available: //! @code //! auto d = xrange(); //! auto d = xrange(end_val); //! auto d = xrange(end_val, param); //! auto d = xrange(begin_val, end_val); //! auto d = xrange(begin_val, end_val, step_val); //! auto d = xrange(param); //! @endcode //! //! - @c begin_val indicates the start of the sequence (default to 0). //! - @c end_val is the end of the sequence. If ommited, the dataset has infinite size.\n //! - @c step_val is the step between two consecutive elements of the sequence, and defaults to 1.\n //! - @c param is the named parameters that describe the sequence. The following parameters are accepted: //! - @c begin: same meaning @c begin_val //! - @c end: same meaning as @c end_val //! - @c step: same meaning as @c step_val //! //! //! The returned value is an object that implements the dataset API. //! //! @note the step size cannot be null, and it should be positive if @c begin_val < @c end_val, negative otherwise. template inline monomorphic::generated_by> xrange( Params const& params ) { return monomorphic::ds_detail::make_xrange::_( params ); } //____________________________________________________________________________// /// @overload boost::unit_test::data::xrange() template inline monomorphic::generated_by> xrange( SampleType const& end_val ) { return monomorphic::ds_detail::make_xrange::_( data::end=end_val ); } //____________________________________________________________________________// /// @overload boost::unit_test::data::xrange() template inline typename enable_if_c::value, monomorphic::generated_by>>::type xrange( SampleType const& end_val, Params const& params ) { return monomorphic::ds_detail::make_xrange::_(( params, data::end=end_val )); } //____________________________________________________________________________// /// @overload boost::unit_test::data::xrange() template inline monomorphic::generated_by> xrange( SampleType const& begin_val, SampleType const& end_val ) { return monomorphic::ds_detail::make_xrange::_(( data::begin=begin_val, data::end=end_val )); } //____________________________________________________________________________// /// @overload boost::unit_test::data::xrange() template inline monomorphic::generated_by> xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val ) { return monomorphic::ds_detail::make_xrange::_(( data::begin=begin_val, data::end=end_val, data::step=step_val )); } //____________________________________________________________________________// } // namespace data } // namespace unit_test } // namespace boost #include #endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER