1 // Copyright (C) 2003, Fernando Luis Cacciola Carballal.
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 
8 
9 //
10 // NOTE: This file is intended to be used ONLY by the test files
11 //       from the Numeric Conversions Library
12 //
13 //
14 #include <cmath>
15 
16 #include "boost/limits.hpp"
17 #include "boost/utility.hpp"
18 
19 #include "boost/test/included/test_exec_monitor.hpp"
20 
21 // Convenience macros to help with compilers which don't parse
22 // explicit template function instantiations (MSVC6)
23 #define MATCH_FNTPL_ARG(t) t const*
24 #define SET_FNTPL_ARG(t) (static_cast< t const* >(0))
25 
26 //
27 // *Minimal* example of a User Defined Numeric Type
28 //
29 //
30 namespace MyUDT
31 {
32 
33 template<class T>
34 struct UDT
35 {
36   typedef T builtin_type ;
37 
UDTMyUDT::UDT38   UDT ( T v_ ) : v (v_) {}
39 
to_builtinMyUDT::UDT40   T to_builtin() const { return v ; }
41 
operator ==(UDT const & lhs,UDT const & rhs)42   friend bool operator == ( UDT const& lhs, UDT const& rhs )
43     { return lhs.to_builtin() == rhs.to_builtin() ; }
44 
45   // NOTE: This operator is *required* by the Numeric Conversion Library
46   //       if Turnc<> is used as the Float2IntRounder policy.
operator <(UDT const & lhs,UDT const & rhs)47   friend bool operator < ( UDT const& lhs, UDT const& rhs )
48     { return lhs.to_builtin() < rhs.to_builtin() ; }
49 
operator <<(std::ostream & os,UDT const & n)50   friend std::ostream& operator << ( std::ostream& os, UDT const& n )
51     { return os << n.to_builtin() ; }
52 
53   T v ;
54 } ;
55 
56 typedef UDT<int>    MyInt ;
57 typedef UDT<double> MyFloat ;
58 
59 //
60 // The Float2IntRounder policies *require* a visible 'ceil' or 'floor' math function
61 // with standard semantics.
62 // In a conformant compiler, ADL can pick these functions even if they are defined
63 // within a user namespace, as below.
64 //
ceil(MyInt const & x)65 inline MyInt ceil  ( MyInt const& x ) { return x ; }
floor(MyInt const & x)66 inline MyInt floor ( MyInt const& x ) { return x ; }
67 
floor(MyFloat const & x)68 inline MyFloat floor ( MyFloat const& x )
69 {
70 #if !defined(BOOST_NO_STDC_NAMESPACE)
71   return MyFloat ( std::floor(x.to_builtin()) ) ;
72 #else
73   return MyFloat ( ::floor(x.to_builtin()) ) ;
74 #endif
75 }
76 
ceil(MyFloat const & x)77 inline MyFloat ceil ( MyFloat const& x )
78 {
79 #if !defined(BOOST_NO_STDC_NAMESPACE)
80   return MyFloat ( std::ceil(x.to_builtin()) ) ;
81 #else
82   return MyFloat ( ::ceil(x.to_builtin()) ) ;
83 #endif
84 }
85 
86 } // namespace MyUDT
87 
88 
89 //
90 // The Numeric Conversion Library *requires* User Defined Numeric Types
91 // to properly specialize std::numeric_limits<>
92 //
93 namespace std
94 {
95 
96 template<>
97 class numeric_limits<MyUDT::MyInt> : public numeric_limits<int>
98 {
99   public :
100 
101     BOOST_STATIC_CONSTANT(bool, is_specialized = false);
102 } ;
103 
104 template<>
105 class numeric_limits<MyUDT::MyFloat> : public numeric_limits<double>
106 {
107   public :
108 
109     BOOST_STATIC_CONSTANT(bool, is_specialized = false);
110 } ;
111 
112 } // namespace std
113 
114 
115 
116 //
117 // The functions floor and ceil defined within namespace MyUDT
118 // should be found by koenig loopkup, but some compilers don't do it right
119 // so we inyect them into namespace std so ordinary overload resolution
120 // can found them.
121 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP) || defined(__BORLANDC__) || defined(__GNUC__)
122 namespace std {
123 using MyUDT::floor ;
124 using MyUDT::ceil  ;
125 } // namespace std
126 #endif
127 
128 
to_string(bool arg)129 std::string to_string( bool arg )
130 {
131   return arg ? "true" : "false" ;
132 }
133 
to_string(...)134 std::string to_string( ... ) { throw std::runtime_error("to_string() called with wrong type!") ; }
135 
136 //
137 // This is used to print 'char' values as numbers instead of characters.
138 //
139 template<class T> struct printable_number_type   { typedef T type ; } ;
140 template<> struct printable_number_type<signed char>   { typedef int type ; } ;
141 template<> struct printable_number_type<unsigned char> { typedef unsigned type ; } ;
142 template<> struct printable_number_type<char>          { typedef int type ; } ;
143 
144 template<class T>
145 inline
146 typename printable_number_type<T>::type
printable(T n)147 printable( T n ) { return n ; }
148 
149 
150 //
151 ///////////////////////////////////////////////////////////////////////////////////////////////
152 
153