summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/numeric/conversion
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/numeric/conversion')
-rw-r--r--src/boost/libs/numeric/conversion/README.md8
-rw-r--r--src/boost/libs/numeric/conversion/index.html13
-rw-r--r--src/boost/libs/numeric/conversion/meta/libraries.json16
-rw-r--r--src/boost/libs/numeric/conversion/test/Jamfile.v242
-rw-r--r--src/boost/libs/numeric/conversion/test/bounds_test.cpp101
-rw-r--r--src/boost/libs/numeric/conversion/test/compile_fail/built_in_numeric_cast_traits.cpp122
-rw-r--r--src/boost/libs/numeric/conversion/test/converter_test.cpp562
-rw-r--r--src/boost/libs/numeric/conversion/test/numeric_cast_test.cpp97
-rw-r--r--src/boost/libs/numeric/conversion/test/numeric_cast_traits_test.cpp380
-rw-r--r--src/boost/libs/numeric/conversion/test/test_helpers.cpp152
-rw-r--r--src/boost/libs/numeric/conversion/test/test_helpers2.cpp60
-rw-r--r--src/boost/libs/numeric/conversion/test/test_helpers3.cpp144
-rw-r--r--src/boost/libs/numeric/conversion/test/traits_test.cpp341
-rw-r--r--src/boost/libs/numeric/conversion/test/udt_example_0.cpp242
-rw-r--r--src/boost/libs/numeric/conversion/test/udt_support_test.cpp309
15 files changed, 2589 insertions, 0 deletions
diff --git a/src/boost/libs/numeric/conversion/README.md b/src/boost/libs/numeric/conversion/README.md
new file mode 100644
index 00000000..987f0ecf
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/README.md
@@ -0,0 +1,8 @@
+# Boost.NumericConversion
+
+The Boost Numeric Conversion library is a collection of tools to describe and perform conversions between values of different [numeric types][1].
+
+The documentation for the library can be found [here][2]
+
+[1]: http://www.boost.org/doc/libs/release/libs/numeric/conversion/doc/html/boost_numericconversion/definitions.html#boost_numericconversion.definitions.numeric_types
+[2]: http://www.boost.org/doc/libs/release/libs/numeric/conversion/doc/html/index.html#numeric_conversion.overview
diff --git a/src/boost/libs/numeric/conversion/index.html b/src/boost/libs/numeric/conversion/index.html
new file mode 100644
index 00000000..305b7385
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/index.html
@@ -0,0 +1,13 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+</head>
+<body>
+Automatic redirection failed, please go to
+<a href="doc/html/index.html">doc/index.html</a>.&nbsp;<hr>
+<p>� Copyright Beman Dawes, 2001</p>
+<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
+file <a href="../../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
+at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
+</body>
+</html>
diff --git a/src/boost/libs/numeric/conversion/meta/libraries.json b/src/boost/libs/numeric/conversion/meta/libraries.json
new file mode 100644
index 00000000..945591c8
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/meta/libraries.json
@@ -0,0 +1,16 @@
+{
+ "key": "numeric/conversion",
+ "name": "Numeric Conversion",
+ "authors": [
+ "Fernando Cacciola"
+ ],
+ "description": "Optimized Policy-based Numeric Conversions.",
+ "category": [
+ "Math",
+ "Miscellaneous"
+ ],
+ "maintainers": [
+ "Fernando Cacciola <fernando_cacciola -at- ciudad.com.ar>",
+ "Brandon Kohn <blkohn -at- hotmail.com>"
+ ]
+}
diff --git a/src/boost/libs/numeric/conversion/test/Jamfile.v2 b/src/boost/libs/numeric/conversion/test/Jamfile.v2
new file mode 100644
index 00000000..16f3eba3
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/Jamfile.v2
@@ -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 : : : <toolset>msvc:<cxxflags>/bigobj ]
+ [ 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 ;
diff --git a/src/boost/libs/numeric/conversion/test/bounds_test.cpp b/src/boost/libs/numeric/conversion/test/bounds_test.cpp
new file mode 100644
index 00000000..504c47c5
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/bounds_test.cpp
@@ -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;
+}
+
diff --git a/src/boost/libs/numeric/conversion/test/compile_fail/built_in_numeric_cast_traits.cpp b/src/boost/libs/numeric/conversion/test/compile_fail/built_in_numeric_cast_traits.cpp
new file mode 100644
index 00000000..c795d88b
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/compile_fail/built_in_numeric_cast_traits.cpp
@@ -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
diff --git a/src/boost/libs/numeric/conversion/test/converter_test.cpp b/src/boost/libs/numeric/conversion/test/converter_test.cpp
new file mode 100644
index 00000000..a460df15
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/converter_test.cpp
@@ -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;
+}
+//---------------------------------------------------------------------------
+
diff --git a/src/boost/libs/numeric/conversion/test/numeric_cast_test.cpp b/src/boost/libs/numeric/conversion/test/numeric_cast_test.cpp
new file mode 100644
index 00000000..f94393cb
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/numeric_cast_test.cpp
@@ -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
diff --git a/src/boost/libs/numeric/conversion/test/numeric_cast_traits_test.cpp b/src/boost/libs/numeric/conversion/test/numeric_cast_traits_test.cpp
new file mode 100644
index 00000000..f59cb6bc
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/numeric_cast_traits_test.cpp
@@ -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
diff --git a/src/boost/libs/numeric/conversion/test/test_helpers.cpp b/src/boost/libs/numeric/conversion/test/test_helpers.cpp
new file mode 100644
index 00000000..5f2d88d3
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/test_helpers.cpp
@@ -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 ; }
+
+
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/boost/libs/numeric/conversion/test/test_helpers2.cpp b/src/boost/libs/numeric/conversion/test/test_helpers2.cpp
new file mode 100644
index 00000000..8fca50b6
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/test_helpers2.cpp
@@ -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!)" ;
+}
+
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/boost/libs/numeric/conversion/test/test_helpers3.cpp b/src/boost/libs/numeric/conversion/test/test_helpers3.cpp
new file mode 100644
index 00000000..de345ba8
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/test_helpers3.cpp
@@ -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 )
+
+
+//
+///////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/boost/libs/numeric/conversion/test/traits_test.cpp b/src/boost/libs/numeric/conversion/test/traits_test.cpp
new file mode 100644
index 00000000..d8d620b7
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/traits_test.cpp
@@ -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;
+}
+//---------------------------------------------------------------------------
+
diff --git a/src/boost/libs/numeric/conversion/test/udt_example_0.cpp b/src/boost/libs/numeric/conversion/test/udt_example_0.cpp
new file mode 100644
index 00000000..067e5e7a
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/udt_example_0.cpp
@@ -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;
+}
+
+
+
+
+
+
diff --git a/src/boost/libs/numeric/conversion/test/udt_support_test.cpp b/src/boost/libs/numeric/conversion/test/udt_support_test.cpp
new file mode 100644
index 00000000..581b0e50
--- /dev/null
+++ b/src/boost/libs/numeric/conversion/test/udt_support_test.cpp
@@ -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;
+}
+
+
+
+
+
+