225 lines
7.3 KiB
C++
225 lines
7.3 KiB
C++
// (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 <boost/test/data/config.hpp>
|
|
|
|
#include <boost/test/data/monomorphic/generators/keywords.hpp>
|
|
#include <boost/test/data/monomorphic/generate.hpp>
|
|
|
|
// Boost
|
|
#include <boost/optional.hpp>
|
|
#include <boost/utility/enable_if.hpp>
|
|
#include <boost/type_traits/is_unsigned.hpp>
|
|
|
|
// STL
|
|
#include <limits>
|
|
#include <cmath>
|
|
|
|
#include <boost/test/detail/suppress_warnings.hpp>
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
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<typename SampleType, typename StepType=SampleType>
|
|
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<typename SampleType, typename StepType=SampleType>
|
|
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<SampleType, StepType> range_gen;
|
|
|
|
template<typename Params>
|
|
static generated_by<range_gen>
|
|
_( Params const& params )
|
|
{
|
|
SampleType begin_val = params.has( data::begin ) ? params[data::begin] : SampleType();
|
|
optional<SampleType> end_val = params.has( data::end ) ? params[data::end] : optional<SampleType>();
|
|
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<StepType>::type*)0 );
|
|
std::size_t s = static_cast<std::size_t>(abs_distance/abs_step);
|
|
|
|
if( static_cast<SampleType>(s*abs_step) < abs_distance )
|
|
s++;
|
|
|
|
size = s;
|
|
}
|
|
|
|
return generated_by<range_gen>( 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<typename SampleType, typename Params>
|
|
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
|
|
xrange( Params const& params )
|
|
{
|
|
return monomorphic::ds_detail::make_xrange<SampleType>::_( params );
|
|
}
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
/// @overload boost::unit_test::data::xrange()
|
|
template<typename SampleType>
|
|
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
|
|
xrange( SampleType const& end_val )
|
|
{
|
|
return monomorphic::ds_detail::make_xrange<SampleType>::_( data::end=end_val );
|
|
}
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
/// @overload boost::unit_test::data::xrange()
|
|
template<typename SampleType, typename Params>
|
|
inline typename enable_if_c<nfp::is_named_param_pack<Params>::value,
|
|
monomorphic::generated_by<monomorphic::xrange_t<SampleType>>>::type
|
|
xrange( SampleType const& end_val, Params const& params )
|
|
{
|
|
return monomorphic::ds_detail::make_xrange<SampleType>::_(( params, data::end=end_val ));
|
|
}
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
/// @overload boost::unit_test::data::xrange()
|
|
template<typename SampleType>
|
|
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
|
|
xrange( SampleType const& begin_val, SampleType const& end_val )
|
|
{
|
|
return monomorphic::ds_detail::make_xrange<SampleType>::_((
|
|
data::begin=begin_val,
|
|
data::end=end_val ));
|
|
}
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
|
|
|
|
/// @overload boost::unit_test::data::xrange()
|
|
template<typename SampleType,typename StepType>
|
|
inline monomorphic::generated_by<monomorphic::xrange_t<SampleType>>
|
|
xrange( SampleType const& begin_val, SampleType const& end_val, StepType const& step_val )
|
|
{
|
|
return monomorphic::ds_detail::make_xrange<SampleType,StepType>::_((
|
|
data::begin=begin_val,
|
|
data::end=end_val,
|
|
data::step=step_val ));
|
|
}
|
|
|
|
//____________________________________________________________________________//
|
|
|
|
} // namespace data
|
|
} // namespace unit_test
|
|
} // namespace boost
|
|
|
|
#include <boost/test/detail/enable_warnings.hpp>
|
|
|
|
#endif // BOOST_TEST_DATA_MONOMORPHIC_GENERATORS_XRANGE_HPP_112011GER
|