mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-28 06:23:23 -04:00
Squashed 'boost/' content from commit b4feb19f2
git-subtree-dir: boost git-subtree-split: b4feb19f287ee92d87a9624b5d36b7cf46aeadeb
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Boost Numeric Conversion Library test Jamfile
|
||||
#
|
||||
# Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
#
|
||||
# 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)
|
||||
#
|
||||
# import testing ;
|
||||
|
||||
project numeric_conversion_unit_tests
|
||||
:
|
||||
requirements
|
||||
<include>.
|
||||
<toolset>gcc:<cxxflags>"-ftemplate-depth-300 -g0"
|
||||
<toolset>darwin:<cxxflags>"-ftemplate-depth-300 -g0"
|
||||
;
|
||||
|
||||
test-suite minimal
|
||||
:
|
||||
[ run bounds_test.cpp ]
|
||||
[ run traits_test.cpp ]
|
||||
[ run converter_test.cpp ]
|
||||
[ run udt_support_test.cpp ]
|
||||
[ run numeric_cast_test.cpp ]
|
||||
[ run udt_example_0.cpp ]
|
||||
[ run numeric_cast_traits_test.cpp ]
|
||||
;
|
||||
|
||||
test-suite full
|
||||
:
|
||||
minimal
|
||||
[ compile-fail compile_fail/built_in_numeric_cast_traits.cpp ]
|
||||
;
|
||||
|
||||
test-suite extra ;
|
||||
|
||||
explicit minimal ;
|
||||
explicit extra ;
|
||||
|
||||
# support the old test target
|
||||
test-suite numeric/conversion : full ;
|
||||
@@ -0,0 +1,101 @@
|
||||
// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
|
||||
// Use, modification, and distribution is subject to 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 library home page at http://www.boost.org/libs/numeric/conversion
|
||||
//
|
||||
// Contact the author at: fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<typeinfo>
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
|
||||
#include "boost/numeric/conversion/bounds.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "test_helpers.cpp"
|
||||
|
||||
using namespace std ;
|
||||
using namespace boost ;
|
||||
using namespace numeric ;
|
||||
|
||||
// Test the fields of boost::numeric::bounds<> against the expected values.
|
||||
//
|
||||
template<class T>
|
||||
void test_bounds( T expected_lowest, T expected_highest, T expected_smallest )
|
||||
{
|
||||
T lowest = bounds<T>::lowest () ;
|
||||
T highest = bounds<T>::highest () ;
|
||||
T smallest = bounds<T>::smallest() ;
|
||||
|
||||
BOOST_CHECK_MESSAGE ( lowest == expected_lowest,
|
||||
"bounds<" << typeid(T).name() << ">::lowest() = " << printable(lowest) << ". Expected " << printable(expected_lowest)
|
||||
) ;
|
||||
|
||||
BOOST_CHECK_MESSAGE ( highest == expected_highest,
|
||||
"bounds<" << typeid(T).name() << ">::highest() = " << printable(highest) << ". Expected " << printable(expected_highest)
|
||||
) ;
|
||||
|
||||
BOOST_CHECK_MESSAGE ( smallest == expected_smallest,
|
||||
"bounds<" << typeid(T).name() << ">::smallest() = " << printable(smallest) << ". Expected " << printable(expected_smallest)
|
||||
) ;
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void test_bounds_integer( MATCH_FNTPL_ARG(T) )
|
||||
{
|
||||
test_bounds( numeric_limits<T>::min BOOST_PREVENT_MACRO_SUBSTITUTION()
|
||||
, numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION()
|
||||
, static_cast<T>(1)
|
||||
) ;
|
||||
}
|
||||
template<class T>
|
||||
void test_bounds_float( MATCH_FNTPL_ARG(T))
|
||||
{
|
||||
test_bounds( -numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
, numeric_limits<T>::max BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
, numeric_limits<T>::min BOOST_PREVENT_MACRO_SUBSTITUTION ()
|
||||
) ;
|
||||
}
|
||||
|
||||
void test_bounds_integers()
|
||||
{
|
||||
test_bounds_integer( SET_FNTPL_ARG(unsigned char) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(signed char) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(char) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(unsigned short) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(short) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(unsigned int) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(int) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(unsigned long) ) ;
|
||||
test_bounds_integer( SET_FNTPL_ARG(long) ) ;
|
||||
}
|
||||
|
||||
void test_bounds_floats()
|
||||
{
|
||||
test_bounds_float( SET_FNTPL_ARG(float) );
|
||||
test_bounds_float( SET_FNTPL_ARG(double) );
|
||||
test_bounds_float( SET_FNTPL_ARG(long double) );
|
||||
}
|
||||
|
||||
void test_bounds()
|
||||
{
|
||||
test_bounds_integers() ;
|
||||
test_bounds_floats () ;
|
||||
}
|
||||
|
||||
|
||||
int test_main( int, char * [] )
|
||||
{
|
||||
cout << setprecision( std::numeric_limits<long double>::digits10 ) ;
|
||||
|
||||
test_bounds();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
//
|
||||
//! Copyright (c) 2011
|
||||
//! Brandon Kohn
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/preprocessor/control/iif.hpp>
|
||||
#include <boost/preprocessor/comparison/less.hpp>
|
||||
#include <boost/preprocessor/comparison/not_equal.hpp>
|
||||
#include <boost/preprocessor/repetition/for.hpp>
|
||||
#include <boost/preprocessor/tuple/elem.hpp>
|
||||
#include <boost/preprocessor/seq/elem.hpp>
|
||||
#include <boost/preprocessor/seq/size.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
//! Generate default traits for the specified source and target.
|
||||
#define BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS(r, state) \
|
||||
template <> \
|
||||
struct numeric_cast_traits< \
|
||||
BOOST_PP_SEQ_ELEM( BOOST_PP_TUPLE_ELEM(4,0,state) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,3,state) ) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,2,state)> \
|
||||
{ \
|
||||
typedef def_overflow_handler overflow_policy; \
|
||||
typedef UseInternalRangeChecker range_checking_policy; \
|
||||
typedef Trunc<BOOST_PP_TUPLE_ELEM(4,2,state)> rounding_policy; \
|
||||
}; \
|
||||
/***/
|
||||
|
||||
#define BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL(r, state) \
|
||||
BOOST_PP_LESS \
|
||||
( \
|
||||
BOOST_PP_TUPLE_ELEM(4,0,state) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,1,state) \
|
||||
) \
|
||||
/***/
|
||||
|
||||
#define BOOST_NUMERIC_CONVERSION_INC_OP(r, state) \
|
||||
( \
|
||||
BOOST_PP_INC(BOOST_PP_TUPLE_ELEM(4,0,state)) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,1,state) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,2,state) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,3,state) \
|
||||
) \
|
||||
/***/
|
||||
|
||||
#define BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP(r, state) \
|
||||
BOOST_PP_FOR \
|
||||
( \
|
||||
( \
|
||||
0 \
|
||||
, BOOST_PP_TUPLE_ELEM(4,1,state) \
|
||||
, BOOST_PP_SEQ_ELEM(BOOST_PP_TUPLE_ELEM(4,0,state),BOOST_PP_TUPLE_ELEM(4,2,state)) \
|
||||
, BOOST_PP_TUPLE_ELEM(4,2,state) \
|
||||
) \
|
||||
, BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL \
|
||||
, BOOST_NUMERIC_CONVERSION_INC_OP \
|
||||
, BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS \
|
||||
) \
|
||||
/***/
|
||||
|
||||
#define BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS(types) \
|
||||
BOOST_PP_FOR \
|
||||
( \
|
||||
(0,BOOST_PP_SEQ_SIZE(types),types,_) \
|
||||
, BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL \
|
||||
, BOOST_NUMERIC_CONVERSION_INC_OP \
|
||||
, BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP \
|
||||
) \
|
||||
/***/
|
||||
|
||||
namespace boost { namespace numeric {
|
||||
#if !defined( BOOST_NO_INT64_T )
|
||||
//! Generate the specializations for the built-in types.
|
||||
BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
|
||||
(
|
||||
(char)
|
||||
(boost::int8_t)
|
||||
(boost::uint8_t)
|
||||
(boost::int16_t)
|
||||
(boost::uint16_t)
|
||||
(boost::int32_t)
|
||||
(boost::uint32_t)
|
||||
(boost::int64_t)
|
||||
(boost::uint64_t)
|
||||
(float)
|
||||
(double)
|
||||
(long double)
|
||||
)
|
||||
#else
|
||||
BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
|
||||
(
|
||||
(char)
|
||||
(boost::int8_t)
|
||||
(boost::uint8_t)
|
||||
(boost::int16_t)
|
||||
(boost::uint16_t)
|
||||
(boost::int32_t)
|
||||
(boost::uint32_t)
|
||||
(float)
|
||||
(double)
|
||||
(long double)
|
||||
)
|
||||
#endif
|
||||
}}//namespace boost::numeric;
|
||||
|
||||
int test_main( int argc, char * argv[] )
|
||||
{
|
||||
//! This test should not compile.
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef BOOST_NUMERIC_CONVERSION_GENERATE_BUILTIN_CAST_TRAITS
|
||||
#undef BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TARGET_STEP
|
||||
#undef BOOST_NUMERIC_CONVERSION_INC_OP
|
||||
#undef BOOST_NUMERIC_CONVERSION_TUPLE_SENTINAL
|
||||
#undef BOOST_NUMERIC_CONVERSION_GENERATE_CAST_TRAITS
|
||||
@@ -0,0 +1,562 @@
|
||||
// (c) Copyright Fernando Luis Cacciola Carballal 2000-2004
|
||||
// Use, modification, and distribution is subject to 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 library home page at http://www.boost.org/libs/numeric/conversion
|
||||
//
|
||||
// Contact the author at: fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include<cstdlib>
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
#include<string>
|
||||
#include<typeinfo>
|
||||
#include<vector>
|
||||
#include<algorithm>
|
||||
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/cstdint.hpp"
|
||||
#include "boost/utility.hpp"
|
||||
|
||||
//
|
||||
// Borland 5.5 lacks the following math overloads
|
||||
//
|
||||
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x551)
|
||||
namespace std
|
||||
{
|
||||
|
||||
inline float ceil (float x) { return std::ceil ( static_cast<double>(x)); }
|
||||
inline float floor (float x) { return std::floor ( static_cast<double>(x)); }
|
||||
inline long double ceil (long double x) { return std::ceill (x); }
|
||||
inline long double floor (long double x) { return std::floorl(x); }
|
||||
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
#include "boost/numeric/conversion/converter.hpp"
|
||||
#include "boost/numeric/conversion/cast.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "test_helpers.cpp"
|
||||
#include "test_helpers2.cpp"
|
||||
#include "test_helpers3.cpp"
|
||||
|
||||
#include "boost/mpl/alias.hpp"
|
||||
|
||||
using std::cout ;
|
||||
|
||||
// A generic 'abs' function.
|
||||
template<class N> inline N absG ( N v )
|
||||
{
|
||||
return v < static_cast<N>(0) ? static_cast<N>(-v) : v ;
|
||||
}
|
||||
template<> inline unsigned char absG<unsigned char> ( unsigned char v ) { return v ; }
|
||||
template<> inline unsigned short absG<unsigned short> ( unsigned short v ) { return v ; }
|
||||
template<> inline unsigned int absG<unsigned int> ( unsigned int v ) { return v ; }
|
||||
template<> inline unsigned long absG<unsigned long> ( unsigned long v ) { return v ; }
|
||||
|
||||
template<class T> inline void unused_variable ( T const& ) {}
|
||||
//
|
||||
// The following function excersizes specific conversions that cover
|
||||
// usual and boundary cases for each relevant combination.
|
||||
//
|
||||
void test_conversions()
|
||||
{
|
||||
using namespace boost ;
|
||||
using namespace numeric ;
|
||||
|
||||
// To help the test found possible bugs a random numbers are used.
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::rand ;
|
||||
#endif
|
||||
|
||||
boost::int16_t v16 ;
|
||||
boost::uint16_t uv16 ;
|
||||
boost::int32_t v32 ;
|
||||
boost::uint32_t uv32 ;
|
||||
|
||||
volatile float fv ; // avoid this to be cached internally in some fpu register
|
||||
volatile double dv ; // avoid this to be cached internally in some fpu register
|
||||
|
||||
//
|
||||
// sample (representative) conversions:
|
||||
//
|
||||
cout << "Testing representative conversions\n";
|
||||
|
||||
// integral to integral
|
||||
|
||||
// signed to signed
|
||||
|
||||
// not subranged
|
||||
v16 = static_cast<boost::int16_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,boost::int16_t,v16,v16);
|
||||
|
||||
// subranged
|
||||
v16 = static_cast<boost::int16_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::int16_t,boost::int32_t,v16,v16);
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::int32_t,bounds<boost::int16_t>::highest() + boost::int32_t(1) ) ;
|
||||
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::int32_t,bounds<boost::int16_t>::lowest() - boost::int32_t(1) ) ;
|
||||
|
||||
// signed to unsigned
|
||||
|
||||
// subranged
|
||||
v32 = absG(static_cast<boost::int32_t>(rand()));
|
||||
v16 = absG(static_cast<boost::int16_t>(rand()));
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint32_t,boost::int32_t,v32,v32);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint16_t,boost::int32_t,v16,v16);
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::uint16_t,boost::int32_t,bounds<boost::uint16_t>::highest() + boost::int32_t(1) ) ;
|
||||
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::uint32_t,boost::int32_t,boost::int32_t(-1) ) ;
|
||||
|
||||
// unsigned to signed
|
||||
|
||||
// not subranged
|
||||
v32 = absG(static_cast<boost::int32_t>(rand()));
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,boost::uint32_t,v32,v32);
|
||||
|
||||
// subranged
|
||||
v16 = absG(static_cast<boost::int16_t>(rand()));
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::int16_t,boost::uint32_t,v16,v16);
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int32_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int16_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
|
||||
|
||||
// unsigned to unsigned
|
||||
|
||||
// not subranged
|
||||
uv16 = static_cast<boost::uint16_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint32_t,boost::uint16_t,uv16,uv16);
|
||||
|
||||
// subranged
|
||||
uv16 = static_cast<boost::uint16_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::uint16_t,boost::uint32_t,uv16,uv16);
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::uint16_t,boost::uint32_t,bounds<boost::uint32_t>::highest() ) ;
|
||||
|
||||
// integral to float
|
||||
|
||||
// from signed integral
|
||||
v32 = static_cast<boost::int32_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(double,boost::int32_t,v32,v32);
|
||||
|
||||
// from uint32_tegral
|
||||
uv32 = static_cast<boost::uint32_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(double,boost::uint32_t,uv32,uv32);
|
||||
|
||||
// float to integral
|
||||
|
||||
// to signed integral
|
||||
v32 = static_cast<boost::int32_t>(rand());
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(boost::int32_t,double,v32,v32);
|
||||
|
||||
dv = static_cast<double>(bounds<boost::uint32_t>::highest()) + 1.0 ;
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(boost::int32_t,double,dv) ;
|
||||
TEST_NEG_OVERFLOW_CONVERSION_DEF(boost::int32_t,double,-dv) ;
|
||||
|
||||
// float to float
|
||||
|
||||
// not subranged
|
||||
fv = static_cast<float>(rand()) / static_cast<float>(3) ;
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(double,float,fv,fv);
|
||||
|
||||
|
||||
// subranged
|
||||
fv = static_cast<float>(rand()) / static_cast<float>(3) ;
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(float,double,fv,fv);
|
||||
TEST_POS_OVERFLOW_CONVERSION_DEF(float,double,bounds<double>::highest()) ;
|
||||
TEST_NEG_OVERFLOW_CONVERSION_DEF(float,double,bounds<double>::lowest ()) ;
|
||||
}
|
||||
|
||||
// Custom OverflowHandler
|
||||
struct custom_overflow_handler
|
||||
{
|
||||
void operator() ( boost::numeric::range_check_result r )
|
||||
{
|
||||
if ( r == boost::numeric::cNegOverflow )
|
||||
cout << "negative_overflow detected!\n" ;
|
||||
else if ( r == boost::numeric::cPosOverflow )
|
||||
cout << "positive_overflow detected!\n" ;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<class T, class S,class OverflowHandler>
|
||||
void test_overflow_handler( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S), MATCH_FNTPL_ARG(OverflowHandler),
|
||||
PostCondition pos,
|
||||
PostCondition neg
|
||||
)
|
||||
{
|
||||
typedef boost::numeric::conversion_traits<T,S> traits ;
|
||||
typedef boost::numeric::converter<T,S,traits,OverflowHandler> converter ;
|
||||
|
||||
static const S psrc = boost::numeric::bounds<S>::highest();
|
||||
static const S nsrc = boost::numeric::bounds<S>::lowest ();
|
||||
|
||||
static const T pres = static_cast<T>(psrc);
|
||||
static const T nres = static_cast<T>(nsrc);
|
||||
|
||||
test_conv_base ( ConversionInstance<converter>(pres,psrc,pos) ) ;
|
||||
test_conv_base ( ConversionInstance<converter>(nres,nsrc,neg) ) ;
|
||||
}
|
||||
|
||||
template<class T, class S>
|
||||
void test_overflow_handlers( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
|
||||
{
|
||||
cout << "Testing Silent Overflow Handler policy\n";
|
||||
|
||||
test_overflow_handler( SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(S),
|
||||
SET_FNTPL_ARG(boost::numeric::silent_overflow_handler),
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
|
||||
cout << "Testing Default Overflow Handler policy\n";
|
||||
|
||||
test_overflow_handler( SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(S),
|
||||
SET_FNTPL_ARG(boost::numeric::def_overflow_handler),
|
||||
c_pos_overflow,
|
||||
c_neg_overflow
|
||||
) ;
|
||||
|
||||
cout << "Testing Custom (User-Defined) Overflow Handler policy\n";
|
||||
|
||||
test_overflow_handler( SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(S),
|
||||
SET_FNTPL_ARG(custom_overflow_handler),
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
}
|
||||
|
||||
// For a given float-type number 'n' of integer value (n.0), check the conversions
|
||||
// within the range [n-1,n+1] taking values at: (n-1,n-0.5,n,n+0.5,n+1).
|
||||
// For each sampled value there is an expected result and a PostCondition according to the
|
||||
// specified round_style.
|
||||
//
|
||||
template<class T, class S, class Float2IntRounder>
|
||||
void test_rounding_conversion ( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(Float2IntRounder),
|
||||
S s,
|
||||
PostCondition resl1,
|
||||
PostCondition resl0,
|
||||
PostCondition res,
|
||||
PostCondition resr0,
|
||||
PostCondition resr1
|
||||
)
|
||||
{
|
||||
typedef boost::numeric::conversion_traits<T,S> Traits ;
|
||||
|
||||
typedef boost::numeric::converter<T,S, Traits, boost::numeric::def_overflow_handler,Float2IntRounder>
|
||||
Converter ;
|
||||
|
||||
S sl1 = s - static_cast<S>(1);
|
||||
S sl0 = s - static_cast<S>(0.5);
|
||||
S sr0 = s + static_cast<S>(0.5);
|
||||
S sr1 = s + static_cast<S>(1);
|
||||
|
||||
T tl1 = static_cast<T>( Converter::nearbyint(sl1) );
|
||||
T tl0 = static_cast<T>( Converter::nearbyint(sl0) );
|
||||
T t = static_cast<T>( Converter::nearbyint(s) );
|
||||
T tr0 = static_cast<T>( Converter::nearbyint(sr0) );
|
||||
T tr1 = static_cast<T>( Converter::nearbyint(sr1) );
|
||||
|
||||
test_conv_base ( ConversionInstance<Converter>(tl1,sl1,resl1) ) ;
|
||||
test_conv_base ( ConversionInstance<Converter>(tl0,sl0,resl0) ) ;
|
||||
test_conv_base ( ConversionInstance<Converter>(t,s,res) ) ;
|
||||
test_conv_base ( ConversionInstance<Converter>(tr0,sr0,resr0) ) ;
|
||||
test_conv_base ( ConversionInstance<Converter>(tr1,sr1,resr1) ) ;
|
||||
}
|
||||
|
||||
|
||||
template<class T,class S>
|
||||
void test_round_style( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
|
||||
{
|
||||
S min = boost::numeric::bounds<T>::lowest();
|
||||
S max = boost::numeric::bounds<T>::highest();
|
||||
|
||||
cout << "Testing 'Trunc' Float2IntRounder policy\n";
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Trunc<S>),
|
||||
min,
|
||||
c_neg_overflow,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Trunc<S>),
|
||||
max,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_pos_overflow
|
||||
) ;
|
||||
|
||||
cout << "Testing 'RoundEven' Float2IntRounder policy\n";
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::RoundEven<S>),
|
||||
min,
|
||||
c_neg_overflow,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::RoundEven<S>),
|
||||
max,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_pos_overflow,
|
||||
c_pos_overflow
|
||||
) ;
|
||||
|
||||
cout << "Testing 'Ceil' Float2IntRounder policy\n";
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Ceil<S>),
|
||||
min,
|
||||
c_neg_overflow,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Ceil<S>),
|
||||
max,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_pos_overflow,
|
||||
c_pos_overflow
|
||||
) ;
|
||||
|
||||
cout << "Testing 'Floor' Float2IntRounder policy\n" ;
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Floor<S>),
|
||||
min,
|
||||
c_neg_overflow,
|
||||
c_neg_overflow,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted
|
||||
) ;
|
||||
|
||||
test_rounding_conversion(SET_FNTPL_ARG(T),
|
||||
SET_FNTPL_ARG(boost::numeric::Floor<S>),
|
||||
max,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_converted,
|
||||
c_pos_overflow
|
||||
) ;
|
||||
|
||||
}
|
||||
|
||||
void test_round_even( double n, double x )
|
||||
{
|
||||
double r = boost::numeric::RoundEven<double>::nearbyint(n);
|
||||
BOOST_CHECK( r == x ) ;
|
||||
}
|
||||
|
||||
void test_round_even()
|
||||
{
|
||||
cout << "Testing 'RoundEven' tie-breaking\n";
|
||||
|
||||
double min = boost::numeric::bounds<double>::lowest();
|
||||
double max = boost::numeric::bounds<double>::highest();
|
||||
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::floor ;
|
||||
using std::ceil ;
|
||||
#endif
|
||||
test_round_even(min, floor(min));
|
||||
test_round_even(max, ceil (max));
|
||||
test_round_even(2.0, 2.0);
|
||||
test_round_even(2.3, 2.0);
|
||||
test_round_even(2.5, 2.0);
|
||||
test_round_even(2.7, 3.0);
|
||||
test_round_even(3.0, 3.0);
|
||||
test_round_even(3.3, 3.0);
|
||||
test_round_even(3.5, 4.0);
|
||||
test_round_even(3.7, 4.0);
|
||||
}
|
||||
|
||||
int double_to_int ( double n ) { return static_cast<int>(n) ; }
|
||||
|
||||
void test_converter_as_function_object()
|
||||
{
|
||||
cout << "Testing converter as function object.\n";
|
||||
|
||||
// Create a sample sequence of double values.
|
||||
std::vector<double> S ;
|
||||
for ( int i = 0 ; i < 10 ; ++ i )
|
||||
S.push_back( i * ( 18.0 / 19.0 ) );
|
||||
|
||||
// Create a sequence of int values from 's' using the standard conversion.
|
||||
std::vector<int> W ;
|
||||
std::transform(S.begin(),S.end(),std::back_inserter(W),double_to_int);
|
||||
|
||||
// Create a sequence of int values from s using a default numeric::converter
|
||||
std::vector<int> I ;
|
||||
std::transform(S.begin(),
|
||||
S.end(),
|
||||
std::back_inserter(I),
|
||||
boost::numeric::converter<int,double>()
|
||||
) ;
|
||||
|
||||
// Match 'w' and 'i' which should be equal.
|
||||
bool double_to_int_OK = std::equal(W.begin(),W.end(),I.begin()) ;
|
||||
BOOST_CHECK_MESSAGE(double_to_int_OK, "converter (int,double) as function object");
|
||||
|
||||
// Create a sequence of double values from s using a default numeric::converter (which should be the trivial conv).
|
||||
std::vector<double> D ;
|
||||
std::transform(S.begin(),
|
||||
S.end(),
|
||||
std::back_inserter(D),
|
||||
boost::numeric::converter<double,double>()
|
||||
) ;
|
||||
|
||||
// Match 's' and 'd' which should be equal.
|
||||
bool double_to_double_OK = std::equal(S.begin(),S.end(),D.begin()) ;
|
||||
BOOST_CHECK_MESSAGE(double_to_double_OK, "converter (double,double) as function object");
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(__IBMCPP__, <= 600 ) // VCAPP6
|
||||
# define UNOPTIMIZED
|
||||
#else
|
||||
# define UNOPTIMIZED volatile
|
||||
#endif
|
||||
|
||||
void test_optimizations()
|
||||
{
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
|
||||
float fv0 = 18.0f / 19.0f ;
|
||||
|
||||
// This code deosn't produce any output.
|
||||
// It is intended to show the optimization of numeric::converter<> by manual inspection
|
||||
// of the generated code.
|
||||
// Each test shows first the equivalent hand-coded version.
|
||||
// The numeric_cast<> code should be the same if full compiler optimization/inlining is used.
|
||||
|
||||
//---------------------------------
|
||||
// trivial conversion.
|
||||
//
|
||||
// equivalent code:
|
||||
UNOPTIMIZED float fv1a = fv0 ;
|
||||
|
||||
float fv1b = numeric_cast<float>(fv0);
|
||||
unused_variable(fv1a);
|
||||
unused_variable(fv1b);
|
||||
//
|
||||
//---------------------------------
|
||||
|
||||
//---------------------------------
|
||||
// nonsubranged conversion.
|
||||
//
|
||||
// equivalent code:
|
||||
UNOPTIMIZED double dv1a = static_cast<double>(fv0);
|
||||
|
||||
double dv1b = numeric_cast<double>(fv0);
|
||||
unused_variable(dv1a);
|
||||
unused_variable(dv1b);
|
||||
//
|
||||
//---------------------------------
|
||||
|
||||
//------------------------------------------------------
|
||||
// subranged conversion with both-sided range checking.
|
||||
//
|
||||
|
||||
// equivalent code:
|
||||
|
||||
{
|
||||
double const& s = dv1b ;
|
||||
// range checking
|
||||
range_check_result r = s < static_cast<double>(bounds<float>::lowest())
|
||||
? cNegOverflow : cInRange ;
|
||||
if ( r == cInRange )
|
||||
{
|
||||
r = s > static_cast<double>(bounds<float>::highest()) ? cPosOverflow : cInRange ;
|
||||
}
|
||||
if ( r == cNegOverflow )
|
||||
throw negative_overflow() ;
|
||||
else if ( r == cPosOverflow )
|
||||
throw positive_overflow() ;
|
||||
// conversion
|
||||
UNOPTIMIZED float fv2a = static_cast<float>(s);
|
||||
unused_variable(fv2a);
|
||||
}
|
||||
|
||||
float fv2b = numeric_cast<float>(dv1b);
|
||||
unused_variable(fv2b);
|
||||
//
|
||||
//---------------------------------
|
||||
|
||||
|
||||
//---------------------------------
|
||||
// subranged rounding conversion
|
||||
//
|
||||
// equivalent code:
|
||||
|
||||
{
|
||||
double const& s = dv1b ;
|
||||
// range checking
|
||||
range_check_result r = s <= static_cast<double>(bounds<int>::lowest()) - static_cast<double>(1.0)
|
||||
? cNegOverflow : cInRange ;
|
||||
if ( r == cInRange )
|
||||
{
|
||||
r = s >= static_cast<double>(bounds<int>::highest()) + static_cast<double>(1.0)
|
||||
? cPosOverflow : cInRange ;
|
||||
}
|
||||
if ( r == cNegOverflow )
|
||||
throw negative_overflow() ;
|
||||
else if ( r == cPosOverflow )
|
||||
throw positive_overflow() ;
|
||||
// rounding
|
||||
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::floor ;
|
||||
#endif
|
||||
|
||||
double s1 = floor(dv1b + 0.5);
|
||||
|
||||
// conversion
|
||||
UNOPTIMIZED int iv1a = static_cast<int>(s1);
|
||||
unused_variable(iv1a);
|
||||
}
|
||||
|
||||
int iv1b = numeric_cast<int>(dv1b);
|
||||
unused_variable(iv1b);
|
||||
//
|
||||
//---------------------------------
|
||||
}
|
||||
|
||||
int test_main( int, char* argv[] )
|
||||
{
|
||||
std::cout << std::setprecision( std::numeric_limits<long double>::digits10 ) ;
|
||||
|
||||
test_conversions();
|
||||
test_overflow_handlers( SET_FNTPL_ARG(boost::int16_t), SET_FNTPL_ARG(boost::int32_t));
|
||||
test_round_style(SET_FNTPL_ARG(boost::int32_t), SET_FNTPL_ARG(double) ) ;
|
||||
test_round_even() ;
|
||||
test_converter_as_function_object();
|
||||
test_optimizations() ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// boost utility cast test program -----------------------------------------//
|
||||
|
||||
// (C) Copyright Beman Dawes, Dave Abrahams 1999. 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 for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 28 Set 04 taken from the old cast library (Fernando Cacciola)
|
||||
|
||||
#include <iostream>
|
||||
#include <climits>
|
||||
#include <cfloat> // for DBL_MAX (Peter Schmid)
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include "boost/test/minimal.hpp"
|
||||
|
||||
# if SCHAR_MAX == LONG_MAX
|
||||
# error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
|
||||
# endif
|
||||
|
||||
using namespace boost;
|
||||
using std::cout;
|
||||
|
||||
int test_main( int argc, char * argv[] )
|
||||
{
|
||||
|
||||
# ifdef NDEBUG
|
||||
cout << "NDEBUG is defined\n";
|
||||
# else
|
||||
cout << "NDEBUG is not defined\n";
|
||||
# endif
|
||||
|
||||
cout << "\nBeginning tests...\n";
|
||||
|
||||
// test implicit_cast and numeric_cast -------------------------------------//
|
||||
|
||||
// tests which should succeed
|
||||
long small_value = 1;
|
||||
long small_negative_value = -1;
|
||||
long large_value = LONG_MAX;
|
||||
long large_negative_value = LONG_MIN;
|
||||
signed char c = 0;
|
||||
|
||||
c = large_value; // see if compiler generates warning
|
||||
|
||||
c = numeric_cast<signed char>( small_value );
|
||||
BOOST_CHECK( c == 1 );
|
||||
c = 0;
|
||||
c = numeric_cast<signed char>( small_value );
|
||||
BOOST_CHECK( c == 1 );
|
||||
c = 0;
|
||||
c = numeric_cast<signed char>( small_negative_value );
|
||||
BOOST_CHECK( c == -1 );
|
||||
|
||||
// These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
|
||||
BOOST_CHECK( 0.0f == numeric_cast<float>( 0.0 ) );
|
||||
BOOST_CHECK( 0.0 == numeric_cast<double>( 0.0 ) );
|
||||
|
||||
// tests which should result in errors being detected
|
||||
|
||||
bool caught_exception = false;
|
||||
try { c = numeric_cast<signed char>( large_value ); }
|
||||
catch ( numeric::bad_numeric_cast )
|
||||
{ cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
|
||||
BOOST_CHECK ( caught_exception );
|
||||
|
||||
caught_exception = false;
|
||||
try { c = numeric_cast<signed char>( large_negative_value ); }
|
||||
catch ( numeric::bad_numeric_cast )
|
||||
{ cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
|
||||
BOOST_CHECK ( caught_exception );
|
||||
|
||||
unsigned long ul;
|
||||
caught_exception = false;
|
||||
try { ul = numeric_cast<unsigned long>( large_negative_value ); }
|
||||
catch ( numeric::bad_numeric_cast )
|
||||
{ cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
|
||||
BOOST_CHECK ( caught_exception );
|
||||
|
||||
caught_exception = false;
|
||||
try { ul = numeric_cast<unsigned long>( small_negative_value ); }
|
||||
catch ( numeric::bad_numeric_cast )
|
||||
{ cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
|
||||
BOOST_CHECK ( caught_exception );
|
||||
|
||||
caught_exception = false;
|
||||
try { numeric_cast<int>( DBL_MAX ); }
|
||||
catch ( numeric::bad_numeric_cast )
|
||||
{ cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
|
||||
BOOST_CHECK ( caught_exception );
|
||||
|
||||
return 0 ;
|
||||
|
||||
} // main
|
||||
@@ -0,0 +1,380 @@
|
||||
//
|
||||
//! Copyright (c) 2011
|
||||
//! Brandon Kohn
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
#include <boost/operators.hpp>
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/test/minimal.hpp>
|
||||
|
||||
//! Define a simple custom number
|
||||
struct Double
|
||||
{
|
||||
Double()
|
||||
: v(0)
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
explicit Double( T v )
|
||||
: v(static_cast<double>(v))
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
Double& operator= ( T t )
|
||||
{
|
||||
v = static_cast<double>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator < ( const Double& rhs ) const
|
||||
{
|
||||
return v < rhs.v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator < ( T rhs ) const
|
||||
{
|
||||
return v < static_cast<double>(rhs);
|
||||
}
|
||||
|
||||
template <typename LHS>
|
||||
friend bool operator < ( const LHS& lhs, const Double& rhs )
|
||||
{
|
||||
return lhs < rhs.v;
|
||||
}
|
||||
|
||||
bool operator > ( const Double& rhs ) const
|
||||
{
|
||||
return v > rhs.v;
|
||||
}
|
||||
|
||||
template <typename LHS>
|
||||
friend bool operator > ( const LHS& lhs, const Double& rhs )
|
||||
{
|
||||
return lhs > rhs.v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator > ( T rhs ) const
|
||||
{
|
||||
return v > static_cast<double>(rhs);
|
||||
}
|
||||
|
||||
bool operator == ( const Double& rhs ) const
|
||||
{
|
||||
return v == rhs.v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator == ( T rhs ) const
|
||||
{
|
||||
return v == static_cast<double>(rhs);
|
||||
}
|
||||
|
||||
template <typename LHS>
|
||||
friend bool operator == ( const LHS& lhs, const Double& rhs )
|
||||
{
|
||||
return lhs == rhs.v;
|
||||
}
|
||||
|
||||
bool operator !() const
|
||||
{
|
||||
return v == 0;
|
||||
}
|
||||
|
||||
Double operator -() const
|
||||
{
|
||||
return Double(-v);
|
||||
}
|
||||
|
||||
Double& operator +=( const Double& t )
|
||||
{
|
||||
v += t.v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Double& operator +=( T t )
|
||||
{
|
||||
v += static_cast<double>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Double& operator -=( const Double& t )
|
||||
{
|
||||
v -= t.v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Double& operator -=( T t )
|
||||
{
|
||||
v -= static_cast<double>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Double& operator *= ( const Double& factor )
|
||||
{
|
||||
v *= factor.v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Double& operator *=( T t )
|
||||
{
|
||||
v *= static_cast<double>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Double& operator /= (const Double& divisor)
|
||||
{
|
||||
v /= divisor.v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Double& operator /=( T t )
|
||||
{
|
||||
v /= static_cast<double>(t);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
double v;
|
||||
};
|
||||
|
||||
//! Define numeric_limits for the custom type.
|
||||
namespace std
|
||||
{
|
||||
template<>
|
||||
class numeric_limits< Double > : public numeric_limits<double>
|
||||
{
|
||||
public:
|
||||
|
||||
//! Limit our Double to a range of +/- 100.0
|
||||
static Double (min)()
|
||||
{
|
||||
return Double(1.e-2);
|
||||
}
|
||||
|
||||
static Double (max)()
|
||||
{
|
||||
return Double(1.e2);
|
||||
}
|
||||
|
||||
static Double epsilon()
|
||||
{
|
||||
return Double( std::numeric_limits<double>::epsilon() );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//! Define range checking and overflow policies.
|
||||
namespace custom
|
||||
{
|
||||
//! Define a custom range checker
|
||||
template<typename Traits, typename OverFlowHandler>
|
||||
struct range_checker
|
||||
{
|
||||
typedef typename Traits::argument_type argument_type ;
|
||||
typedef typename Traits::source_type S;
|
||||
typedef typename Traits::target_type T;
|
||||
|
||||
//! Check range of integral types.
|
||||
static boost::numeric::range_check_result out_of_range( argument_type s )
|
||||
{
|
||||
using namespace boost::numeric;
|
||||
if( s > bounds<T>::highest() )
|
||||
return cPosOverflow;
|
||||
else if( s < bounds<T>::lowest() )
|
||||
return cNegOverflow;
|
||||
else
|
||||
return cInRange;
|
||||
}
|
||||
|
||||
static void validate_range ( argument_type s )
|
||||
{
|
||||
BOOST_STATIC_ASSERT( std::numeric_limits<T>::is_bounded );
|
||||
OverFlowHandler()( out_of_range(s) );
|
||||
}
|
||||
};
|
||||
|
||||
//! Overflow handler
|
||||
struct positive_overflow{};
|
||||
struct negative_overflow{};
|
||||
|
||||
struct overflow_handler
|
||||
{
|
||||
void operator() ( boost::numeric::range_check_result r )
|
||||
{
|
||||
using namespace boost::numeric;
|
||||
if( r == cNegOverflow )
|
||||
throw negative_overflow() ;
|
||||
else if( r == cPosOverflow )
|
||||
throw positive_overflow() ;
|
||||
}
|
||||
};
|
||||
|
||||
//! Define a rounding policy and specialize on the custom type.
|
||||
template<class S>
|
||||
struct Ceil : boost::numeric::Ceil<S>{};
|
||||
|
||||
template<>
|
||||
struct Ceil<Double>
|
||||
{
|
||||
typedef Double source_type;
|
||||
|
||||
typedef Double const& argument_type;
|
||||
|
||||
static source_type nearbyint ( argument_type s )
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::ceil ;
|
||||
#endif
|
||||
return Double( ceil(s.v) );
|
||||
}
|
||||
|
||||
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_infinity> round_style;
|
||||
};
|
||||
|
||||
//! Define a rounding policy and specialize on the custom type.
|
||||
template<class S>
|
||||
struct Trunc: boost::numeric::Trunc<S>{};
|
||||
|
||||
template<>
|
||||
struct Trunc<Double>
|
||||
{
|
||||
typedef Double source_type;
|
||||
|
||||
typedef Double const& argument_type;
|
||||
|
||||
static source_type nearbyint ( argument_type s )
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
using std::floor;
|
||||
#endif
|
||||
return Double( floor(s.v) );
|
||||
}
|
||||
|
||||
typedef boost::mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style;
|
||||
};
|
||||
}//namespace custom;
|
||||
|
||||
namespace boost { namespace numeric {
|
||||
|
||||
//! Define the numeric_cast_traits specializations on the custom type.
|
||||
template <typename S>
|
||||
struct numeric_cast_traits<Double, S>
|
||||
{
|
||||
typedef custom::overflow_handler overflow_policy;
|
||||
typedef custom::range_checker
|
||||
<
|
||||
boost::numeric::conversion_traits<Double, S>
|
||||
, overflow_policy
|
||||
> range_checking_policy;
|
||||
typedef boost::numeric::Trunc<S> rounding_policy;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct numeric_cast_traits<T, Double>
|
||||
{
|
||||
typedef custom::overflow_handler overflow_policy;
|
||||
typedef custom::range_checker
|
||||
<
|
||||
boost::numeric::conversion_traits<T, Double>
|
||||
, overflow_policy
|
||||
> range_checking_policy;
|
||||
typedef custom::Trunc<Double> rounding_policy;
|
||||
};
|
||||
|
||||
//! Define the conversion from the custom type to built-in types and vice-versa.
|
||||
template<typename T>
|
||||
struct raw_converter< conversion_traits< T, Double > >
|
||||
{
|
||||
static T low_level_convert ( const Double& n )
|
||||
{
|
||||
return static_cast<T>( n.v );
|
||||
}
|
||||
};
|
||||
|
||||
template<typename S>
|
||||
struct raw_converter< conversion_traits< Double, S > >
|
||||
{
|
||||
static Double low_level_convert ( const S& n )
|
||||
{
|
||||
return Double(n);
|
||||
}
|
||||
};
|
||||
}}//namespace boost::numeric;
|
||||
|
||||
#define BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW( CastCode ) \
|
||||
try { CastCode; BOOST_CHECK( false ); } \
|
||||
catch( custom::positive_overflow& ){} \
|
||||
catch(...){ BOOST_CHECK( false ); } \
|
||||
/***/
|
||||
|
||||
#define BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW( CastCode ) \
|
||||
try { CastCode; BOOST_CHECK( false ); } \
|
||||
catch( custom::negative_overflow& ){} \
|
||||
catch(...){ BOOST_CHECK( false ); } \
|
||||
/***/
|
||||
|
||||
struct test_cast_traits
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
Double d = boost::numeric_cast<Double>( static_cast<T>(50) );
|
||||
BOOST_CHECK( d.v == 50. );
|
||||
T v = boost::numeric_cast<T>( d );
|
||||
BOOST_CHECK( v == 50 );
|
||||
}
|
||||
};
|
||||
|
||||
void test_numeric_cast_traits()
|
||||
{
|
||||
typedef boost::mpl::vector
|
||||
<
|
||||
boost::int8_t
|
||||
, boost::uint8_t
|
||||
, boost::int16_t
|
||||
, boost::uint16_t
|
||||
, boost::int32_t
|
||||
, boost::uint32_t
|
||||
#if !defined( BOOST_NO_INT64_T )
|
||||
, boost::int64_t
|
||||
, boost::uint64_t
|
||||
#endif
|
||||
, float
|
||||
, double
|
||||
, long double
|
||||
> types;
|
||||
boost::mpl::for_each<types>( test_cast_traits() );
|
||||
|
||||
//! Check overflow handler.
|
||||
Double d( 56.0 );
|
||||
BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW( d = boost::numeric_cast<Double>( 101 ) );
|
||||
BOOST_CHECK( d.v == 56. );
|
||||
BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW( d = boost::numeric_cast<Double>( -101 ) );
|
||||
BOOST_CHECK( d.v == 56.);
|
||||
|
||||
//! Check custom round policy.
|
||||
d = 5.9;
|
||||
int five = boost::numeric_cast<int>( d );
|
||||
BOOST_CHECK( five == 5 );
|
||||
}
|
||||
|
||||
int test_main( int argc, char * argv[] )
|
||||
{
|
||||
test_numeric_cast_traits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef BOOST_TEST_CATCH_CUSTOM_POSITIVE_OVERFLOW
|
||||
#undef BOOST_TEST_CATCH_CUSTOM_NEGATIVE_OVERFLOW
|
||||
@@ -0,0 +1,152 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// NOTE: This file is intended to be used ONLY by the test files
|
||||
// from the Numeric Conversions Library
|
||||
//
|
||||
//
|
||||
#include <cmath>
|
||||
|
||||
#include "boost/limits.hpp"
|
||||
#include "boost/utility.hpp"
|
||||
|
||||
#include "boost/test/included/test_exec_monitor.hpp"
|
||||
|
||||
// Convenience macros to help with compilers which don't parse
|
||||
// explicit template function instantiations (MSVC6)
|
||||
#define MATCH_FNTPL_ARG(t) t const*
|
||||
#define SET_FNTPL_ARG(t) (static_cast< t const* >(0))
|
||||
|
||||
//
|
||||
// *Minimal* example of a User Defined Numeric Type
|
||||
//
|
||||
//
|
||||
namespace MyUDT
|
||||
{
|
||||
|
||||
template<class T>
|
||||
struct UDT
|
||||
{
|
||||
typedef T builtin_type ;
|
||||
|
||||
UDT ( T v_ ) : v (v_) {}
|
||||
|
||||
T to_builtin() const { return v ; }
|
||||
|
||||
friend bool operator == ( UDT const& lhs, UDT const& rhs )
|
||||
{ return lhs.to_builtin() == rhs.to_builtin() ; }
|
||||
|
||||
// NOTE: This operator is *required* by the Numeric Conversion Library
|
||||
// if Turnc<> is used as the Float2IntRounder policy.
|
||||
friend bool operator < ( UDT const& lhs, UDT const& rhs )
|
||||
{ return lhs.to_builtin() < rhs.to_builtin() ; }
|
||||
|
||||
friend std::ostream& operator << ( std::ostream& os, UDT const& n )
|
||||
{ return os << n.to_builtin() ; }
|
||||
|
||||
T v ;
|
||||
} ;
|
||||
|
||||
typedef UDT<int> MyInt ;
|
||||
typedef UDT<double> MyFloat ;
|
||||
|
||||
//
|
||||
// The Float2IntRounder policies *require* a visible 'ceil' or 'floor' math function
|
||||
// with standard semantics.
|
||||
// In a conformant compiler, ADL can pick these functions even if they are defined
|
||||
// within a user namespace, as below.
|
||||
//
|
||||
inline MyInt ceil ( MyInt const& x ) { return x ; }
|
||||
inline MyInt floor ( MyInt const& x ) { return x ; }
|
||||
|
||||
inline MyFloat floor ( MyFloat const& x )
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
return MyFloat ( std::floor(x.to_builtin()) ) ;
|
||||
#else
|
||||
return MyFloat ( ::floor(x.to_builtin()) ) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline MyFloat ceil ( MyFloat const& x )
|
||||
{
|
||||
#if !defined(BOOST_NO_STDC_NAMESPACE)
|
||||
return MyFloat ( std::ceil(x.to_builtin()) ) ;
|
||||
#else
|
||||
return MyFloat ( ::ceil(x.to_builtin()) ) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace MyUDT
|
||||
|
||||
|
||||
//
|
||||
// The Numeric Conversion Library *requires* User Defined Numeric Types
|
||||
// to properly specialize std::numeric_limits<>
|
||||
//
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<>
|
||||
class numeric_limits<MyUDT::MyInt> : public numeric_limits<int>
|
||||
{
|
||||
public :
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
|
||||
} ;
|
||||
|
||||
template<>
|
||||
class numeric_limits<MyUDT::MyFloat> : public numeric_limits<double>
|
||||
{
|
||||
public :
|
||||
|
||||
BOOST_STATIC_CONSTANT(bool, is_specialized = false);
|
||||
} ;
|
||||
|
||||
} // namespace std
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The functions floor and ceil defined within namespace MyUDT
|
||||
// should be found by koenig loopkup, but some compilers don't do it right
|
||||
// so we inyect them into namespace std so ordinary overload resolution
|
||||
// can found them.
|
||||
#if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || defined(__BORLANDC__) || defined(__GNUC__)
|
||||
namespace std {
|
||||
using MyUDT::floor ;
|
||||
using MyUDT::ceil ;
|
||||
} // namespace std
|
||||
#endif
|
||||
|
||||
|
||||
std::string to_string( bool arg )
|
||||
{
|
||||
return arg ? "true" : "false" ;
|
||||
}
|
||||
|
||||
std::string to_string( ... ) { throw std::runtime_error("to_string() called with wrong type!") ; }
|
||||
|
||||
//
|
||||
// This is used to print 'char' values as numbers instead of characters.
|
||||
//
|
||||
template<class T> struct printable_number_type { typedef T type ; } ;
|
||||
template<> struct printable_number_type<signed char> { typedef int type ; } ;
|
||||
template<> struct printable_number_type<unsigned char> { typedef unsigned type ; } ;
|
||||
template<> struct printable_number_type<char> { typedef int type ; } ;
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
typename printable_number_type<T>::type
|
||||
printable( T n ) { return n ; }
|
||||
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// NOTE: This file is intended to be used ONLY by the test files
|
||||
// from the Numeric Conversions Library
|
||||
//
|
||||
|
||||
//
|
||||
// The following 'to_string' helpers are provided to give readable names
|
||||
// to the various enums used by the library.
|
||||
// NOTE: specializations of boost::lexical_cast<> were not used since some compilers had
|
||||
// trouble dealing with such specializations for different enumerations.
|
||||
//
|
||||
|
||||
std::string to_string ( boost::numeric::int_float_mixture_enum arg )
|
||||
{
|
||||
switch ( arg )
|
||||
{
|
||||
case boost::numeric::integral_to_integral : return "integral_to_integral" ;
|
||||
case boost::numeric::integral_to_float : return "integral_to_float" ;
|
||||
case boost::numeric::float_to_integral : return "float_to_integral" ;
|
||||
case boost::numeric::float_to_float : return "float_to_float" ;
|
||||
}
|
||||
return "(Unknown result!)" ;
|
||||
}
|
||||
|
||||
|
||||
std::string to_string ( boost::numeric::sign_mixture_enum arg )
|
||||
{
|
||||
switch ( arg )
|
||||
{
|
||||
case boost::numeric::unsigned_to_unsigned : return "unsigned_to_unsigned" ;
|
||||
case boost::numeric::signed_to_signed : return "signed_to_signed" ;
|
||||
case boost::numeric::signed_to_unsigned : return "signed_to_unsigned" ;
|
||||
case boost::numeric::unsigned_to_signed : return "unsigned_to_signed" ;
|
||||
}
|
||||
return "(Unknown result!)" ;
|
||||
}
|
||||
|
||||
std::string to_string ( boost::numeric::udt_builtin_mixture_enum arg )
|
||||
{
|
||||
switch ( arg )
|
||||
{
|
||||
case boost::numeric::builtin_to_builtin : return "builtin_to_builtin" ;
|
||||
case boost::numeric::builtin_to_udt : return "builtin_to_udt" ;
|
||||
case boost::numeric::udt_to_builtin : return "udt_to_builtin" ;
|
||||
case boost::numeric::udt_to_udt : return "udt_to_udt" ;
|
||||
}
|
||||
return "(Unknown result!)" ;
|
||||
}
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// NOTE: This file is intended to be used ONLY by the test files
|
||||
// from the Numeric Conversions Library
|
||||
//
|
||||
|
||||
// The conversion test is performed using a class whose instances encapsulate
|
||||
// a particular specific conversion defnied explicitely.
|
||||
// A ConversionInstance object includes the source type, the target type,
|
||||
// the source value and the expected result, including possible exceptions.
|
||||
//
|
||||
|
||||
enum PostCondition { c_converted, c_overflow, c_neg_overflow, c_pos_overflow } ;
|
||||
|
||||
template<class Converter>
|
||||
struct ConversionInstance
|
||||
{
|
||||
typedef Converter converter ;
|
||||
|
||||
typedef typename Converter::argument_type argument_type ;
|
||||
typedef typename Converter::result_type result_type ;
|
||||
|
||||
typedef typename Converter::traits traits ;
|
||||
typedef typename traits::target_type target_type ;
|
||||
typedef typename traits::source_type source_type ;
|
||||
|
||||
ConversionInstance ( result_type a_result, argument_type a_source, PostCondition a_post)
|
||||
:
|
||||
source(a_source),
|
||||
result(a_result),
|
||||
post(a_post)
|
||||
{}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
return std::string("converter<")
|
||||
+ typeid(target_type).name()
|
||||
+ std::string(",")
|
||||
+ typeid(source_type).name()
|
||||
+ std::string(">::convert(") ;
|
||||
}
|
||||
|
||||
argument_type source ;
|
||||
result_type result ;
|
||||
PostCondition post ;
|
||||
} ;
|
||||
|
||||
//
|
||||
// Main conversion test point.
|
||||
// Exercises a specific conversion described by 'conv'.
|
||||
//
|
||||
template<class Instance>
|
||||
void test_conv_base( Instance const& conv )
|
||||
{
|
||||
typedef typename Instance::argument_type argument_type ;
|
||||
typedef typename Instance::result_type result_type ;
|
||||
typedef typename Instance::converter converter ;
|
||||
|
||||
argument_type source = conv.source ;
|
||||
|
||||
try
|
||||
{
|
||||
result_type result = converter::convert(source);
|
||||
|
||||
if ( conv.post == c_converted )
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( result == conv.result,
|
||||
conv.to_string() << printable(source) << ")= " << printable(result) << ". Expected:" << printable(conv.result)
|
||||
) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ERROR( conv.to_string() << printable(source) << ") = " << printable(result)
|
||||
<< ". Expected:" << ( conv.post == c_neg_overflow ? " negative_overflow" : "positive_overflow" )
|
||||
) ;
|
||||
}
|
||||
}
|
||||
catch ( boost::numeric::negative_overflow const& )
|
||||
{
|
||||
if ( conv.post == c_neg_overflow )
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = negative_overflow, as expected" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ERROR( conv.to_string() << printable(source) << ") = negative_overflow. Expected:" << printable(conv.result) ) ;
|
||||
}
|
||||
}
|
||||
catch ( boost::numeric::positive_overflow const& )
|
||||
{
|
||||
if ( conv.post == c_pos_overflow )
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = positive_overflow, as expected" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ERROR( conv.to_string() << printable(source) << ") = positive_overflow. Expected:" << printable(conv.result) ) ;
|
||||
}
|
||||
}
|
||||
catch ( boost::numeric::bad_numeric_cast const& )
|
||||
{
|
||||
if ( conv.post == c_overflow )
|
||||
{
|
||||
BOOST_CHECK_MESSAGE( true, conv.to_string() << printable(source) << ") = bad_numeric_cast, as expected" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_ERROR( conv.to_string() << printable(source) << ") = bad_numeric_cast. Expected:" << printable(conv.result) ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define TEST_SUCCEEDING_CONVERSION(Conv,typeT,typeS,valueT,valueS) \
|
||||
test_conv_base( ConversionInstance< Conv >(valueT, valueS, c_converted ) )
|
||||
|
||||
#define TEST_POS_OVERFLOW_CONVERSION(Conv,typeT,typeS,valueS) \
|
||||
test_conv_base( ConversionInstance< Conv >( static_cast< typeT >(0), valueS, c_pos_overflow ) )
|
||||
|
||||
#define TEST_NEG_OVERFLOW_CONVERSION(Conv,typeT,typeS,valueS) \
|
||||
test_conv_base( ConversionInstance< Conv >( static_cast< typeT >(0), valueS, c_neg_overflow ) )
|
||||
|
||||
#define DEF_CONVERTER(T,S) boost::numeric::converter< T , S >
|
||||
|
||||
#define TEST_SUCCEEDING_CONVERSION_DEF(typeT,typeS,valueT,valueS) \
|
||||
TEST_SUCCEEDING_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueT, valueS )
|
||||
|
||||
#define TEST_POS_OVERFLOW_CONVERSION_DEF(typeT,typeS,valueS) \
|
||||
TEST_POS_OVERFLOW_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueS )
|
||||
|
||||
#define TEST_NEG_OVERFLOW_CONVERSION_DEF(typeT,typeS,valueS) \
|
||||
TEST_NEG_OVERFLOW_CONVERSION( DEF_CONVERTER(typeT,typeS), typeT, typeS, valueS )
|
||||
|
||||
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
#include<string>
|
||||
#include<typeinfo>
|
||||
#include<vector>
|
||||
#include<algorithm>
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
#include <boost/numeric/conversion/conversion_traits.hpp>
|
||||
#include <boost/numeric/conversion/int_float_mixture.hpp>
|
||||
#include <boost/numeric/conversion/sign_mixture.hpp>
|
||||
#include <boost/numeric/conversion/udt_builtin_mixture.hpp>
|
||||
#include <boost/numeric/conversion/is_subranged.hpp>
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "test_helpers.cpp"
|
||||
#include "test_helpers2.cpp"
|
||||
|
||||
using namespace std ;
|
||||
using namespace boost ;
|
||||
using namespace numeric;
|
||||
using namespace MyUDT ;
|
||||
|
||||
// These helpers are used by generate_expected_traits<T,S>.
|
||||
// Unlike the similar helpers in the implementation, they are specialized by extension.
|
||||
//
|
||||
template<class T, class S> struct my_is_subranged ;
|
||||
template<class T, class S> struct my_is_trivial ;
|
||||
template<class T, class S> struct my_int_float_mixture ;
|
||||
template<class T, class S> struct my_sign_mixture ;
|
||||
template<class T, class S> struct my_udt_builtin_mixture ;
|
||||
|
||||
// This macro is used to define the properties of each conversion between
|
||||
// the builtin arithmetric types
|
||||
//
|
||||
// It defines the specialization of the helper traits used by 'generate_expected_traits'
|
||||
//
|
||||
#define DEFINE_CONVERSION(Target,Source,Trivial,Mixture,SignMixture,UdtMixture,SubRanged) \
|
||||
\
|
||||
template<> struct my_is_subranged<Target,Source> \
|
||||
{ typedef mpl::bool_< (SubRanged) > type ; } ; \
|
||||
\
|
||||
template<> struct my_is_trivial<Target,Source> \
|
||||
{ typedef mpl::bool_< (Trivial) > type ; } ; \
|
||||
\
|
||||
template<> struct my_int_float_mixture<Target,Source> \
|
||||
{ typedef mpl::integral_c<boost::numeric::int_float_mixture_enum, (Mixture) > type ; } ; \
|
||||
\
|
||||
template<> struct my_sign_mixture<Target,Source> \
|
||||
{ typedef mpl::integral_c<boost::numeric::sign_mixture_enum, (SignMixture) > type ; } ; \
|
||||
\
|
||||
template<> struct my_udt_builtin_mixture<Target,Source> \
|
||||
{ typedef mpl::integral_c<boost::numeric::udt_builtin_mixture_enum, (UdtMixture) > type ; }
|
||||
|
||||
|
||||
#define cSubRanged true
|
||||
#define cTrivial true
|
||||
|
||||
// The following test assumes a specific relation between the sizes of the types being used;
|
||||
// therefore, use specific fixed-width types instead built-in types directly.
|
||||
|
||||
// NOTE --> TARGET,SOURCE
|
||||
//
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::uint8_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::uint8_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::uint8_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::int8_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::int8_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::int8_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::uint16_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::uint16_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::uint16_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::int16_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::int16_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::int16_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::uint32_t, cTrivial, integral_to_integral, unsigned_to_unsigned, builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::uint32_t, !cTrivial, integral_to_integral, unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::uint32_t, !cTrivial, integral_to_float , unsigned_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , boost::int32_t, !cTrivial, integral_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , boost::int32_t, cTrivial, integral_to_integral, signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(float , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , boost::int32_t, !cTrivial, integral_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , boost::int32_t, !cTrivial, integral_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , float, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(float , float, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(double , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(float) > sizeof(double) ) );
|
||||
DEFINE_CONVERSION(long double , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(float) > sizeof(long double) ) );
|
||||
DEFINE_CONVERSION(MyInt , float, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , float, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(float , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(double) > sizeof(float) ) );
|
||||
DEFINE_CONVERSION(double , double, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(long double , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(double) > sizeof(long double) ) );
|
||||
DEFINE_CONVERSION(MyInt , double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , double, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , long double, !cTrivial, float_to_integral, signed_to_unsigned, builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_builtin, cSubRanged );
|
||||
DEFINE_CONVERSION(float , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(long double) > sizeof(float) ) );
|
||||
DEFINE_CONVERSION(double , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, ( sizeof(long double) > sizeof(double) ) );
|
||||
DEFINE_CONVERSION(long double , long double, cTrivial, float_to_float , signed_to_signed , builtin_to_builtin, !cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , long double, !cTrivial, float_to_integral, signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , long double, !cTrivial, float_to_float , signed_to_signed , builtin_to_udt , !cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , MyInt, !cTrivial, integral_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , MyInt, !cTrivial, integral_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(float , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(double , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(long double , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , MyInt, cTrivial, integral_to_integral, signed_to_signed , udt_to_udt ,!cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , MyInt, !cTrivial, integral_to_float , signed_to_signed , udt_to_udt ,!cSubRanged );
|
||||
|
||||
DEFINE_CONVERSION(boost::uint8_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int8_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint16_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int16_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::uint32_t , MyFloat, !cTrivial, float_to_integral, signed_to_unsigned, udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(boost::int32_t , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(float , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(double , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(long double , MyFloat, !cTrivial, float_to_float , signed_to_signed , udt_to_builtin , cSubRanged );
|
||||
DEFINE_CONVERSION(MyInt , MyFloat, !cTrivial, float_to_integral, signed_to_signed , udt_to_udt ,!cSubRanged );
|
||||
DEFINE_CONVERSION(MyFloat , MyFloat, cTrivial, float_to_float , signed_to_signed , udt_to_udt ,!cSubRanged );
|
||||
|
||||
//
|
||||
// The test is performed by comparing each field of
|
||||
// boost::numeric::conversion_traits<T,S>
|
||||
// with the fields of
|
||||
// expected_traits<T,S>
|
||||
// which is a traits class constructed explicitely for each combination
|
||||
// of the built-in arithmetic types.
|
||||
//
|
||||
template<class T,
|
||||
class S,
|
||||
class Supertype,
|
||||
class Subtype,
|
||||
class Subranged,
|
||||
class Trivial
|
||||
>
|
||||
struct expected_traits
|
||||
{
|
||||
typedef typename my_int_float_mixture <T,S>::type int_float_mixture ;
|
||||
typedef typename my_sign_mixture <T,S>::type sign_mixture ;
|
||||
typedef typename my_udt_builtin_mixture <T,S>::type udt_builtin_mixture ;
|
||||
|
||||
typedef Subranged subranged ;
|
||||
typedef Trivial trivial ;
|
||||
typedef Supertype supertype ;
|
||||
typedef Subtype subtype ;
|
||||
} ;
|
||||
|
||||
// This is used by the test engine to generate a expected_traits from T and S.
|
||||
//
|
||||
template<class T, class S>
|
||||
struct generate_expected_traits
|
||||
{
|
||||
typedef expected_traits<T, S, T, S, mpl::false_, mpl::true_ > trivial ;
|
||||
typedef expected_traits<T, S, S, T, mpl::true_ , mpl::false_ > subranged ;
|
||||
typedef expected_traits<T, S, T, S, mpl::false_, mpl::false_ > non_subranged ;
|
||||
|
||||
typedef typename my_is_subranged<T,S>::type IsSubranged ;
|
||||
typedef typename my_is_trivial <T,S>::type IsTrivial ;
|
||||
|
||||
typedef typename mpl::if_<IsSubranged,subranged,non_subranged>::type non_trivial ;
|
||||
|
||||
typedef typename mpl::if_<IsTrivial,trivial,non_trivial>::type type ;
|
||||
} ;
|
||||
|
||||
// This macro generates the code that compares a non-type field
|
||||
// in boost::numeric::conversion_traits<> with its corresponding field
|
||||
// in expected_traits<>
|
||||
//
|
||||
|
||||
#define TEST_VALUE_FIELD(Name) \
|
||||
typedef typename traits::Name BOOST_PP_CAT(t,Name) ; \
|
||||
typedef typename expected::Name BOOST_PP_CAT(x,Name) ; \
|
||||
BOOST_CHECK_MESSAGE ( ( BOOST_PP_CAT(t,Name)::value == BOOST_PP_CAT(x,Name)::value ) , \
|
||||
"conversion_traits<" << typeid(T).name() << "," << typeid(S).name() \
|
||||
<< ">::" << #Name << " = " << to_string(BOOST_PP_CAT(t,Name)::value) \
|
||||
<< ". Expected: " << to_string(BOOST_PP_CAT(x,Name)::value) \
|
||||
) ;
|
||||
|
||||
// This macro generates the code that compares a type field
|
||||
// in numeric::conversion_traits<> with its corresponding field
|
||||
// in expected_traits<>
|
||||
//
|
||||
#define TEST_TYPE_FIELD(Name) \
|
||||
typedef typename traits::Name BOOST_PP_CAT(t,Name) ; \
|
||||
typedef typename expected::Name BOOST_PP_CAT(x,Name) ; \
|
||||
BOOST_CHECK_MESSAGE ( ( typeid(BOOST_PP_CAT(t,Name)) == typeid(BOOST_PP_CAT(x,Name)) ) , \
|
||||
"conversion_traits<" << typeid(T).name() << "," << typeid(S).name() \
|
||||
<< ">::" << #Name << " = " << typeid(BOOST_PP_CAT(t,Name)).name() \
|
||||
<< ". Expected: " << typeid(BOOST_PP_CAT(x,Name)).name() \
|
||||
) ;
|
||||
|
||||
//
|
||||
// Test core.
|
||||
// Compares each field of boost::numeric::conversion_traits<T,S>
|
||||
// with the corresponding field of expected_traits<T,S>
|
||||
//
|
||||
template<class T, class S>
|
||||
void test_traits_base( MATCH_FNTPL_ARG(T), MATCH_FNTPL_ARG(S) )
|
||||
{
|
||||
typedef boost::numeric::conversion_traits<T,S> traits ;
|
||||
typedef typename generate_expected_traits<T,S>::type expected ;
|
||||
|
||||
TEST_VALUE_FIELD(int_float_mixture) ;
|
||||
TEST_VALUE_FIELD(sign_mixture) ;
|
||||
TEST_VALUE_FIELD(udt_builtin_mixture) ;
|
||||
TEST_VALUE_FIELD(subranged) ;
|
||||
TEST_VALUE_FIELD(trivial) ;
|
||||
TEST_TYPE_FIELD (supertype) ;
|
||||
TEST_TYPE_FIELD (subtype) ;
|
||||
}
|
||||
|
||||
|
||||
template<class S>
|
||||
void test_traits_from( MATCH_FNTPL_ARG(S) )
|
||||
{
|
||||
test_traits_base( SET_FNTPL_ARG(boost::uint8_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(boost::int8_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(boost::uint16_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(boost::int16_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(boost::uint32_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(boost::int32_t) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(float) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(double) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(long double) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(MyInt) ,SET_FNTPL_ARG(S) );
|
||||
test_traits_base( SET_FNTPL_ARG(MyFloat) ,SET_FNTPL_ARG(S) );
|
||||
}
|
||||
|
||||
void test_traits()
|
||||
{
|
||||
test_traits_from( SET_FNTPL_ARG(boost::uint8_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(boost::int8_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(boost::uint16_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(boost::int16_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(boost::uint32_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(boost::int32_t) );
|
||||
test_traits_from( SET_FNTPL_ARG(float) );
|
||||
test_traits_from( SET_FNTPL_ARG(double) );
|
||||
test_traits_from( SET_FNTPL_ARG(long double) );
|
||||
test_traits_from( SET_FNTPL_ARG(MyInt) );
|
||||
test_traits_from( SET_FNTPL_ARG(MyFloat) );
|
||||
}
|
||||
|
||||
int test_main( int, char * [])
|
||||
{
|
||||
std::cout << std::setprecision( std::numeric_limits<long double>::digits10 ) ;
|
||||
|
||||
test_traits();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
// Copyright (C) 2005, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
#include "boost/config.hpp"
|
||||
#include "boost/utility.hpp"
|
||||
#include "boost/limits.hpp"
|
||||
#include "boost/utility.hpp"
|
||||
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
#include<string>
|
||||
#include<cmath>
|
||||
|
||||
|
||||
#include "boost/test/included/test_exec_monitor.hpp"
|
||||
|
||||
#include "boost/numeric/conversion/cast.hpp"
|
||||
|
||||
using namespace std ;
|
||||
using namespace boost;
|
||||
using namespace numeric;
|
||||
|
||||
//
|
||||
// This example illustrates how to add support for user defined types (UDTs)
|
||||
// to the Boost Numeric Conversion Library.
|
||||
// It is assumed that you are familiar with the following documentation:
|
||||
//
|
||||
//
|
||||
|
||||
//
|
||||
// The minimum requirement is that boost::is_arithmetic<UDT> evaluates to false
|
||||
// (Otherwise the converter code will try to examine the UDT as a built-in type)
|
||||
//
|
||||
|
||||
//
|
||||
// Let's start with the simpliest case of an UDT which supports standard conversions
|
||||
//
|
||||
struct Double
|
||||
{
|
||||
Double( double v ) : mV(v) {}
|
||||
|
||||
operator double() const { return mV ; }
|
||||
|
||||
double mV ;
|
||||
} ;
|
||||
|
||||
double dv = (numeric_limits<double>::max)() ;
|
||||
double fv = (numeric_limits<float >::max)() ;
|
||||
Double Dv(dv);
|
||||
Double Fv(fv);
|
||||
|
||||
void simplest_case()
|
||||
{
|
||||
//
|
||||
// conversion_traits<>::udt_builtin_mixture works out of the box as long as boost::is_arithmetic<UDT> yields false
|
||||
//
|
||||
BOOST_CHECK( (conversion_traits<double,Double>::udt_builtin_mixture::value == udt_to_builtin) ) ;
|
||||
BOOST_CHECK( (conversion_traits<Double,double>::udt_builtin_mixture::value == builtin_to_udt) ) ;
|
||||
BOOST_CHECK( (conversion_traits<Double,Double>::udt_builtin_mixture::value == udt_to_udt ) ) ;
|
||||
|
||||
// BY DEFINITION, a conversion from UDT to Builtin is subranged. No attempt is made to actually compare ranges.
|
||||
BOOST_CHECK( (conversion_traits<double,Double>::subranged::value) == true ) ;
|
||||
BOOST_CHECK( (conversion_traits<Double,double>::subranged::value) == false ) ;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Conversions to/from FLOATING types, if already supported by an UDT
|
||||
// are also supported out-of-the-box by converter<> in its default configuration.
|
||||
//
|
||||
BOOST_CHECK( numeric_cast<double>(Dv) == static_cast<double>(Dv) ) ;
|
||||
BOOST_CHECK( numeric_cast<Double>(dv) == static_cast<Double>(dv) ) ;
|
||||
|
||||
BOOST_CHECK( numeric_cast<float> (Dv) == static_cast<float> (Dv) ) ;
|
||||
BOOST_CHECK( numeric_cast<Double>(fv) == static_cast<Double>(fv) ) ;
|
||||
|
||||
|
||||
//
|
||||
// Range checking is disabled by default if an UDT is either the source or target of the conversion.
|
||||
//
|
||||
BOOST_CHECK( (converter<float,double>::out_of_range(dv) == cPosOverflow) );
|
||||
BOOST_CHECK( (converter<float,Double>::out_of_range(Dv) == cInRange) );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// The conversion_traits<> class and therefore the converter<> class looks at
|
||||
// numeric_limits<UDT>::is_integer/is_signed to generate the proper float_in and sign mixtures.
|
||||
// In most implementations, is_integer/is_signed are both false for UDTs if there is no explicit specialization for it.
|
||||
// Therefore, the converter<> will see any UDT for which numeric_limits<> is not specialized as Float AND unsigned.
|
||||
// Signess is used in the converter<> for range checking, but range checking is disabled by default for UDTs, so,
|
||||
// normally, signess is mostly irrelevant as far as the library is concerned, except for the numeric_traits<>::sign_mixture
|
||||
// entry.
|
||||
// is_integer, however, is relevant in that if the conversion is from a float type to an integer type, the conversion is
|
||||
// "rounding" and the rounder policies will participate.
|
||||
// ALL implemented rounder policies require proper definitions for floor(udt) and ceil(udt).
|
||||
// These names will be searched for using ADL, so, if you need to convert TO integral types from a UDT,
|
||||
// you need to supply those functions along with the UDT in right namespace (that is, any namespace that allows
|
||||
// ADL to find them)
|
||||
|
||||
// If your UDT doesn't supply floor/ceil, conversions to integer types
|
||||
// won't compile unless a custom Float2IntRounder is used.
|
||||
|
||||
Double floor ( Double v ) { return Double(std::floor(v.mV)) ; }
|
||||
Double ceil ( Double v ) { return Double(std::ceil (v.mV)) ; }
|
||||
|
||||
void rounding()
|
||||
{
|
||||
BOOST_CHECK( numeric_cast<int>(Dv) == static_cast<int>(Dv) ) ;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// If your UDT can't or won't provide floor/ceil you can set-up and use your own
|
||||
// Float2IntRounder policy (though doing this is not always required as shown so far)
|
||||
//
|
||||
struct DoubleToInt
|
||||
{
|
||||
static Double nearbyint ( Double const& s ) { return Double(static_cast<int>(s)); }
|
||||
|
||||
typedef mpl::integral_c< std::float_round_style, std::round_toward_zero> round_style ;
|
||||
} ;
|
||||
|
||||
void custom_rounding()
|
||||
{
|
||||
typedef converter<int
|
||||
,Double
|
||||
,conversion_traits<int,Double>
|
||||
,void // By default UDT disable range checking so this won't be used
|
||||
,DoubleToInt
|
||||
>
|
||||
DoubleToIntConverter ;
|
||||
|
||||
BOOST_CHECK( DoubleToIntConverter::convert(Dv) == static_cast<int>(Dv) ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// In the next Level of complexity, your UDTs might not support conversion operators
|
||||
//
|
||||
struct Float
|
||||
{
|
||||
Float( float v ) : mV(v) {}
|
||||
|
||||
float mV ;
|
||||
} ;
|
||||
|
||||
struct Int
|
||||
{
|
||||
Int( int v ) : mV(v) {}
|
||||
|
||||
int mV ;
|
||||
} ;
|
||||
|
||||
typedef conversion_traits<Int,Float> Float2IntTraits ;
|
||||
typedef conversion_traits<Float,Int> Int2FloatTraits ;
|
||||
|
||||
namespace boost { namespace numeric
|
||||
{
|
||||
//
|
||||
// Though static_cast<> won't work with them you can still use numeric_cast<> by specializing
|
||||
// raw_converter as follows:
|
||||
//
|
||||
template<> struct raw_converter<Float2IntTraits>
|
||||
{
|
||||
typedef Float2IntTraits::result_type result_type ;
|
||||
typedef Float2IntTraits::argument_type argument_type ;
|
||||
|
||||
static result_type low_level_convert ( argument_type s ) { return Int((int)s.mV); }
|
||||
} ;
|
||||
template<> struct raw_converter<Int2FloatTraits>
|
||||
{
|
||||
typedef Int2FloatTraits::result_type result_type ;
|
||||
typedef Int2FloatTraits::argument_type argument_type ;
|
||||
|
||||
static result_type low_level_convert ( argument_type s ) { return Float(s.mV); }
|
||||
} ;
|
||||
|
||||
} }
|
||||
|
||||
void custom_raw_converter()
|
||||
{
|
||||
Float f (12.34);
|
||||
Int i (12);
|
||||
Float fi(12);
|
||||
|
||||
BOOST_CHECK(numeric_cast<Int> (f).mV == i .mV ) ;
|
||||
BOOST_CHECK(numeric_cast<Float>(i).mV == fi.mV ) ;
|
||||
}
|
||||
|
||||
//
|
||||
// Alterntively, the custom raw_converter classes can be defined non-instrusively
|
||||
// (not as specializations) and passed along as policies
|
||||
//
|
||||
struct Float2IntRawConverter
|
||||
{
|
||||
static Int low_level_convert ( Float const& s ) { return Int((int)s.mV); }
|
||||
} ;
|
||||
struct Int2FloatRawConverter
|
||||
{
|
||||
static Float low_level_convert ( Int const& s ) { return Float(s.mV); }
|
||||
} ;
|
||||
|
||||
void custom_raw_converter2()
|
||||
{
|
||||
Float f (12.34);
|
||||
Int i (12);
|
||||
Float fi(12);
|
||||
|
||||
typedef converter<Int
|
||||
,Float
|
||||
,Float2IntTraits
|
||||
,void // By default UDT disable range checking so this won't be used
|
||||
,void // Float2Int Rounder won't be used if Int isn't marked as integer via numeric_limits<>
|
||||
,Float2IntRawConverter
|
||||
>
|
||||
Float2IntConverter ;
|
||||
|
||||
BOOST_CHECK(Float2IntConverter::convert(f).mV == i .mV ) ;
|
||||
}
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
cout << setprecision( numeric_limits<long double>::digits10 ) ;
|
||||
|
||||
simplest_case();
|
||||
rounding();
|
||||
custom_rounding();
|
||||
custom_raw_converter();
|
||||
custom_raw_converter2();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
// (C) Copyright 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
//
|
||||
#include<iostream>
|
||||
#include<iomanip>
|
||||
#include<string>
|
||||
#include<typeinfo>
|
||||
#include<vector>
|
||||
#include<algorithm>
|
||||
|
||||
#include "boost/numeric/conversion/converter.hpp"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#include "test_helpers.cpp"
|
||||
#include "test_helpers2.cpp"
|
||||
#include "test_helpers3.cpp"
|
||||
|
||||
using namespace std ;
|
||||
using namespace boost ;
|
||||
using namespace numeric ;
|
||||
using namespace MyUDT ;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// These are the typical steps that are required to install support for
|
||||
// conversions from/to UDT which need special treatment.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
//
|
||||
// (1) Instantiate specific convesions traits.
|
||||
// This step is only for convenience.
|
||||
// These traits instances are required in order to define the specializations
|
||||
// that follow (and which *are required* to make the library work with MyInt and MyFloat)
|
||||
//
|
||||
namespace MyUDT {
|
||||
|
||||
typedef conversion_traits<double , MyFloat> MyFloat_to_double_Traits;
|
||||
typedef conversion_traits<int , MyFloat> MyFloat_to_int_Traits;
|
||||
typedef conversion_traits<MyInt , MyFloat> MyFloat_to_MyInt_Traits;
|
||||
typedef conversion_traits<int , MyInt > MyInt_to_int_Traits;
|
||||
typedef conversion_traits<MyFloat, MyInt > MyInt_to_MyFloat_Traits;
|
||||
typedef conversion_traits<MyInt , double > double_to_MyInt_Traits;
|
||||
|
||||
} // namespace MyUDT
|
||||
|
||||
|
||||
//
|
||||
// (2) Define suitable raw converters.
|
||||
//
|
||||
// Our sample UDTs don't support implicit conversions.
|
||||
// Therefore, the default raw_converter<> doesn't work,
|
||||
// and we need to define our own.
|
||||
//
|
||||
// There are two ways of doing this:
|
||||
//
|
||||
// (a) One is to simply specialize boost::numeric::raw_converter<> directly.
|
||||
// This way, the default converter will work out of the box, which means, for instance,
|
||||
// that numeric_cast<> can be used with these UDTs.
|
||||
//
|
||||
// (b) Define a user class with the appropriate interface and supply it explicitely
|
||||
// as a policy to a converter instance.
|
||||
//
|
||||
// This test uses chice (a).
|
||||
//
|
||||
namespace boost {
|
||||
|
||||
namespace numeric {
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::MyFloat_to_double_Traits>
|
||||
{
|
||||
static double low_level_convert ( MyUDT::MyFloat const& s )
|
||||
{ return s.to_builtin() ; }
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::MyFloat_to_int_Traits>
|
||||
{
|
||||
static int low_level_convert ( MyUDT::MyFloat const& s )
|
||||
{ return static_cast<int>( s.to_builtin() ) ; }
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::MyFloat_to_MyInt_Traits>
|
||||
{
|
||||
static MyUDT::MyInt low_level_convert ( MyUDT::MyFloat const& s )
|
||||
{ return MyUDT::MyInt( static_cast<int>(s.to_builtin()) ) ; }
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::MyInt_to_int_Traits>
|
||||
{
|
||||
static int low_level_convert ( MyUDT::MyInt const& s ) { return s.to_builtin() ; }
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::MyInt_to_MyFloat_Traits>
|
||||
{
|
||||
static MyUDT::MyFloat low_level_convert ( MyUDT::MyInt const& s )
|
||||
{
|
||||
return MyUDT::MyFloat( static_cast<double>(s.to_builtin()) ) ;
|
||||
}
|
||||
} ;
|
||||
|
||||
template<>
|
||||
struct raw_converter<MyUDT::double_to_MyInt_Traits>
|
||||
{
|
||||
static MyUDT::MyInt low_level_convert ( double s )
|
||||
{ return MyUDT::MyInt( static_cast<int>(s) ) ; }
|
||||
} ;
|
||||
|
||||
} // namespace numeric
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
//
|
||||
// (3) Define suitable range checkers
|
||||
//
|
||||
// By default, if a UDT is involved in a conversion, internal range checking is disabled.
|
||||
// This is so because a UDT type can have any sort of range, even unbounded, thus
|
||||
// the library doesn't attempt to automatically figure out the appropriate range checking logic.
|
||||
// (as it does when builtin types are involved)
|
||||
// However, this situation is a bit unsufficient in practice, specially from doing narrowing (subranged)
|
||||
// conversions from UDTs.
|
||||
// The library provides a rudimentary hook to help this out: The user can plug in his own
|
||||
// range checker to the converter instance.
|
||||
//
|
||||
// This test shows how to define and use a custom range checker.
|
||||
//
|
||||
|
||||
namespace MyUDT {
|
||||
|
||||
//
|
||||
// The following are metaprogramming tools to allow us the implement the
|
||||
// MyCustomRangeChecker generically, for either builtin or UDT types.
|
||||
//
|
||||
|
||||
// get_builtin_type<N>::type extracts the built-in type of our UDT's
|
||||
//
|
||||
template<class N> struct get_builtin_type { typedef N type ; } ;
|
||||
template<> struct get_builtin_type<MyInt> { typedef int type ; } ;
|
||||
template<> struct get_builtin_type<MyFloat> { typedef double type ; } ;
|
||||
|
||||
// U extract_builtin ( T s ) returns 's' converted to the corresponding built-in type U.
|
||||
//
|
||||
template<class N>
|
||||
struct extract_builtin
|
||||
{
|
||||
static N apply ( N n ) { return n ; }
|
||||
} ;
|
||||
template<>
|
||||
struct extract_builtin<MyInt>
|
||||
{
|
||||
static int apply ( MyInt const& n ) { return n.to_builtin() ; }
|
||||
} ;
|
||||
template<>
|
||||
struct extract_builtin<MyFloat>
|
||||
{
|
||||
static double apply ( MyFloat const& n ) { return n.to_builtin() ; }
|
||||
} ;
|
||||
|
||||
template<class Traits>
|
||||
struct MyCustomRangeChecker
|
||||
{
|
||||
typedef typename Traits::argument_type argument_type ;
|
||||
|
||||
// This custom range checker uses the fact that our 'fake' UDT are merely wrappers
|
||||
// around builtin types; so it just forward the logic to the correspoding range
|
||||
// checkers for the wrapped builtin types.
|
||||
//
|
||||
typedef typename Traits::source_type S ;
|
||||
typedef typename Traits::target_type T ;
|
||||
|
||||
// NOTE: S and/or T can be either UDT or builtin types.
|
||||
|
||||
typedef typename get_builtin_type<S>::type builtinS ;
|
||||
typedef typename get_builtin_type<T>::type builtinT ;
|
||||
|
||||
// NOTE: The internal range checker used by default is *built* when you instantiate
|
||||
// a converter<> with a given Traits according to the properties of the involved types.
|
||||
// Currently, there is no way to instantiate this range checker as a separate class.
|
||||
// However, you can see it as part of the interface of the converter
|
||||
// (since the converter inherits from it)
|
||||
// Therefore, here we instantiate a converter corresponding to the builtin types to access
|
||||
// their associated builtin range checker.
|
||||
//
|
||||
typedef boost::numeric::converter<builtinT,builtinS> InternalConverter ;
|
||||
|
||||
static range_check_result out_of_range ( argument_type s )
|
||||
{
|
||||
return InternalConverter::out_of_range( extract_builtin<S>::apply(s) );
|
||||
}
|
||||
|
||||
static void validate_range ( argument_type s )
|
||||
{
|
||||
return InternalConverter::validate_range( extract_builtin<S>::apply(s) );
|
||||
}
|
||||
} ;
|
||||
|
||||
} // namespace MyUDT
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Test here
|
||||
//
|
||||
|
||||
void test_udt_conversions_with_defaults()
|
||||
{
|
||||
cout << "Testing UDT conversion with default policies\n" ;
|
||||
|
||||
// MyInt <--> int
|
||||
|
||||
int mibv = rand();
|
||||
MyInt miv(mibv);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(MyInt,int,miv,mibv);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(int,MyInt,mibv,miv);
|
||||
|
||||
// MyFloat <--> double
|
||||
|
||||
double mfbv = static_cast<double>(rand()) / 3.0 ;
|
||||
MyFloat mfv (mfbv);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(MyFloat,double,mfv,mfbv);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(double,MyFloat,mfbv,mfv);
|
||||
|
||||
// MyInt <--> MyFloat
|
||||
|
||||
MyInt miv2 ( static_cast<int>(mfbv) );
|
||||
MyFloat miv2F ( static_cast<int>(mfbv) );
|
||||
MyFloat mfv2 ( static_cast<double>(mibv) );
|
||||
MyInt mfv2I ( static_cast<double>(mibv) );
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(MyFloat,MyInt,miv2F,miv2);
|
||||
TEST_SUCCEEDING_CONVERSION_DEF(MyInt,MyFloat,mfv2I,mfv2);
|
||||
}
|
||||
|
||||
template<class T, class S>
|
||||
struct GenerateCustomConverter
|
||||
{
|
||||
typedef conversion_traits<T,S> Traits;
|
||||
|
||||
typedef def_overflow_handler OverflowHandler ;
|
||||
typedef Trunc<S> Float2IntRounder ;
|
||||
typedef raw_converter<Traits> RawConverter ;
|
||||
typedef MyCustomRangeChecker<Traits> RangeChecker ;
|
||||
|
||||
typedef converter<T,S,Traits,OverflowHandler,Float2IntRounder,RawConverter,RangeChecker> type ;
|
||||
} ;
|
||||
|
||||
void test_udt_conversions_with_custom_range_checking()
|
||||
{
|
||||
cout << "Testing UDT conversions with custom range checker\n" ;
|
||||
|
||||
int mibv = rand();
|
||||
MyFloat mfv ( static_cast<double>(mibv) );
|
||||
|
||||
typedef GenerateCustomConverter<MyFloat,int>::type int_to_MyFloat_Conv ;
|
||||
|
||||
TEST_SUCCEEDING_CONVERSION( int_to_MyFloat_Conv, MyFloat, int, mfv, mibv );
|
||||
|
||||
int mibv2 = rand();
|
||||
MyInt miv (mibv2);
|
||||
MyFloat mfv2 ( static_cast<double>(mibv2) );
|
||||
|
||||
typedef GenerateCustomConverter<MyFloat,MyInt>::type MyInt_to_MyFloat_Conv ;
|
||||
|
||||
TEST_SUCCEEDING_CONVERSION( MyInt_to_MyFloat_Conv, MyFloat, MyInt, mfv2, miv );
|
||||
|
||||
double mfbv = bounds<double>::highest();
|
||||
typedef GenerateCustomConverter<MyInt,double>::type double_to_MyInt_Conv ;
|
||||
|
||||
TEST_POS_OVERFLOW_CONVERSION( double_to_MyInt_Conv, MyInt, double, mfbv );
|
||||
|
||||
MyFloat mfv3 ( bounds<double>::lowest() ) ;
|
||||
typedef GenerateCustomConverter<int,MyFloat>::type MyFloat_to_int_Conv ;
|
||||
|
||||
TEST_NEG_OVERFLOW_CONVERSION( MyFloat_to_int_Conv, int, MyFloat, mfv3 );
|
||||
}
|
||||
|
||||
|
||||
int test_main( int, char* [] )
|
||||
{
|
||||
cout << setprecision( numeric_limits<long double>::digits10 ) ;
|
||||
|
||||
test_udt_conversions_with_defaults();
|
||||
test_udt_conversions_with_custom_range_checking();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user