xrange.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // (C) Copyright Gennadiy Rozental 2001.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // See http://www.boost.org/libs/test for the library home page.
  6. //
  7. ///@file
  8. ///Defines range generator
  9. // ***************************************************************************
  10. #ifndef BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
  11. #define BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
  12. // Boost.Test
  13. #include <boost/test/data/config.hpp>
  14. #include <boost/test/data/monomorphic/generators/keywords.hpp>
  15. #include <boost/test/data/monomorphic/generate.hpp>
  16. // Boost
  17. #include <boost/optional.hpp>
  18. #include <boost/utility/enable_if.hpp>
  19. #include <boost/type_traits/is_unsigned.hpp>
  20. // STL
  21. #include <limits>
  22. #include <cmath>
  23. #include <boost/test/detail/suppress_warnings.hpp>
  24. //____________________________________________________________________________//
  25. namespace boost {
  26. namespace unit_test {
  27. namespace data {
  28. namespace monomorphic {
  29. // ************************************************************************** //
  30. // ************** monomorphic::xrange_t ************** //
  31. // ************************************************************************** //
  32. /*!@brief Generator for the range sequences
  33. *
  34. * This class implements the generator concept (see @ref boost::unit_test::data::monomorphic::generated_by) for implementing
  35. * a range like sequence of numbers.
  36. */
  37. template<typename SampleType, typename StepType=SampleType>
  38. class xrange_t {
  39. public:
  40. typedef SampleType sample;
  41. xrange_t( SampleType const& begin_, StepType const& step_, data::size_t size_ )
  42. : m_begin( begin_ )
  43. , m_curr( begin_ )
  44. , m_step( step_ )
  45. , m_index( 0 )
  46. , m_size( size_ )
  47. {}
  48. // Generator interface
  49. data::size_t capacity() const { return m_size; }
  50. SampleType next()
  51. {
  52. if( m_index == m_size )
  53. return m_curr;
  54. SampleType res = m_curr;
  55. m_curr += m_step;
  56. ++m_index;
  57. return res;
  58. }
  59. void reset()
  60. {
  61. m_curr = m_begin;
  62. m_index = 0;
  63. }
  64. private:
  65. // Data members
  66. SampleType m_begin;
  67. SampleType m_curr;
  68. StepType m_step;
  69. data::size_t m_index;
  70. data::size_t m_size;
  71. };
  72. //____________________________________________________________________________//
  73. namespace ds_detail {
  74. template<typename SampleType, typename StepType=SampleType>
  75. struct make_xrange {
  76. static StepType abs( StepType s, boost::true_type* ) { return s; }
  77. static StepType abs( StepType s, boost::false_type* ) { return std::abs(s); }
  78. typedef xrange_t<SampleType, StepType> range_gen;
  79. template<typename Params>
  80. static generated_by<range_gen>
  81. _( Params const& params )
  82. {
  83. SampleType begin_val = params.has( data::begin ) ? params[data::begin] : SampleType();
  84. optional<SampleType> end_val = params.has( data::end ) ? params[data::end] : optional<SampleType>();
  85. StepType step_val = params.has( data::step ) ? params[data::step] : 1;
  86. BOOST_TEST_DS_ASSERT( step_val != 0, "Range step can't be zero" );
  87. data::size_t size;
  88. if( !end_val.is_initialized() )
  89. size = BOOST_TEST_DS_INFINITE_SIZE;
  90. else {
  91. BOOST_TEST_DS_ASSERT( (step_val < 0) ^ (begin_val < *end_val), "Invalid step direction" );
  92. SampleType abs_distance = step_val < 0 ? begin_val - *end_val : *end_val-begin_val;
  93. StepType abs_step = make_xrange::abs(step_val, (typename boost::is_unsigned<StepType>::type*)0 );
  94. std::size_t s = static_cast<std::size_t>(abs_distance/abs_step);
  95. if( static_cast<SampleType>(s*abs_step) < abs_distance )
  96. s++;
  97. size = s;
  98. }
  99. return generated_by<range_gen>( range_gen( begin_val, step_val, size ) );
  100. }
  101. };
  102. } // namespace ds_detail
  103. } // namespace monomorphic
  104. //____________________________________________________________________________//
  105. //! Creates a range (sequence) dataset.
  106. //!
  107. //! The following overloads are available:
  108. //! @code
  109. //! auto d = xrange();
  110. //! auto d = xrange(end_val);
  111. //! auto d = xrange(end_val, param);
  112. //! auto d = xrange(begin_val, end_val);
  113. //! auto d = xrange(begin_val, end_val, step_val);
  114. //! auto d = xrange(param);
  115. //! @endcode
  116. //!
  117. //! - @c begin_val indicates the start of the sequence (default to 0).
  118. //! - @c end_val is the end of the sequence. If ommited, the dataset has infinite size.\n
  119. //! - @c step_val is the step between two consecutive elements of the sequence, and defaults to 1.\n
  120. //! - @c param is the named parameters that describe the sequence. The following parameters are accepted:
  121. //! - @c begin: same meaning @c begin_val
  122. //! - @c end: same meaning as @c end_val
  123. //! - @c step: same meaning as @c step_val
  124. //!
  125. //!
  126. //! The returned value is an object that implements the dataset API.
  127. //!
  128. //! @note the step size cannot be null, and it should be positive if @c begin_val < @c end_val, negative otherwise.
  129. template<typename SampleType, typename Params>
  130. inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
  131. xrange( Params const& params )
  132. {
  133. return monomorphic::ds_detail::make_xrange<SampleType>::_( params );
  134. }
  135. //____________________________________________________________________________//
  136. /// @overload boost::unit_test::data::xrange()
  137. template<typename SampleType>
  138. inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
  139. xrange( SampleType const& end_val )
  140. {
  141. return monomorphic::ds_detail::make_xrange<SampleType>::_( data::end=end_val );
  142. }
  143. //____________________________________________________________________________//
  144. /// @overload boost::unit_test::data::xrange()
  145. template<typename SampleType, typename Params>
  146. inline typename enable_if_c<nfp::is_named_param_pack<Params>::value,
  147. monomorphic::generated_by<monomorphic::xrange_t<SampleType>>>::type
  148. xrange( SampleType const& end_val, Params const& params )
  149. {
  150. return monomorphic::ds_detail::make_xrange<SampleType>::_(( params, data::end=end_val ));
  151. }
  152. //____________________________________________________________________________//
  153. /// @overload boost::unit_test::data::xrange()
  154. template<typename SampleType>
  155. inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
  156. xrange( SampleType const& begin_val, SampleType const& end_val )
  157. {
  158. return monomorphic::ds_detail::make_xrange<SampleType>::_((
  159. data::begin=begin_val,
  160. data::end=end_val ));
  161. }
  162. //____________________________________________________________________________//
  163. /// @overload boost::unit_test::data::xrange()
  164. template<typename SampleType,typename StepType>
  165. inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
  166. xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val )
  167. {
  168. return monomorphic::ds_detail::make_xrange<SampleType,StepType>::_((
  169. data::begin=begin_val,
  170. data::end=end_val,
  171. data::step=step_val ));
  172. }
  173. //____________________________________________________________________________//
  174. } // namespace data
  175. } // namespace unit_test
  176. } // namespace boost
  177. #include <boost/test/detail/enable_warnings.hpp>
  178. #endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER