mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-25 01:50:30 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			381 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			381 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| //! 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
 |