1 ///////////////////////////////////////////////////////////////
2 //  Copyright 2012 John Maddock. Distributed under the Boost
3 //  Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
5 
6 #ifndef BOOST_MATH_CONCEPTS_ER_HPP
7 #define BOOST_MATH_CONCEPTS_ER_HPP
8 
9 #include <iostream>
10 #include <sstream>
11 #include <iomanip>
12 #include <cmath>
13 #include <boost/cstdint.hpp>
14 #include <boost/multiprecision/number.hpp>
15 #include <boost/math/special_functions/fpclassify.hpp>
16 #include <boost/mpl/list.hpp>
17 
18 namespace boost{
19 namespace multiprecision{
20 namespace concepts{
21 
22 #ifdef BOOST_MSVC
23 #pragma warning(push)
24 #pragma warning(disable:4244)
25 #endif
26 
27 struct number_backend_float_architype
28 {
29    typedef mpl::list<boost::long_long_type>                 signed_types;
30    typedef mpl::list<boost::ulong_long_type>        unsigned_types;
31    typedef mpl::list<long double>               float_types;
32    typedef int                                  exponent_type;
33 
number_backend_float_architypeboost::multiprecision::concepts::number_backend_float_architype34    number_backend_float_architype()
35    {
36       std::cout << "Default construct" << std::endl;
37    }
number_backend_float_architypeboost::multiprecision::concepts::number_backend_float_architype38    number_backend_float_architype(const number_backend_float_architype& o)
39    {
40       std::cout << "Copy construct" << std::endl;
41       m_value = o.m_value;
42    }
operator =boost::multiprecision::concepts::number_backend_float_architype43    number_backend_float_architype& operator = (const number_backend_float_architype& o)
44    {
45       m_value = o.m_value;
46       std::cout << "Assignment (" << m_value << ")" << std::endl;
47       return *this;
48    }
operator =boost::multiprecision::concepts::number_backend_float_architype49    number_backend_float_architype& operator = (boost::ulong_long_type i)
50    {
51       m_value = i;
52       std::cout << "UInt Assignment (" << i << ")" << std::endl;
53       return *this;
54    }
operator =boost::multiprecision::concepts::number_backend_float_architype55    number_backend_float_architype& operator = (boost::long_long_type i)
56    {
57       m_value = i;
58       std::cout << "Int Assignment (" << i << ")" << std::endl;
59       return *this;
60    }
operator =boost::multiprecision::concepts::number_backend_float_architype61    number_backend_float_architype& operator = (long double d)
62    {
63       m_value = d;
64       std::cout << "long double Assignment (" << d << ")" << std::endl;
65       return *this;
66    }
operator =boost::multiprecision::concepts::number_backend_float_architype67    number_backend_float_architype& operator = (const char* s)
68    {
69       try
70       {
71          m_value = boost::lexical_cast<long double>(s);
72       }
73       catch(const std::exception&)
74       {
75          BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse input string: \"") + s + std::string("\" as a valid floating point number.")));
76       }
77       std::cout << "const char* Assignment (" << s << ")" << std::endl;
78       return *this;
79    }
swapboost::multiprecision::concepts::number_backend_float_architype80    void swap(number_backend_float_architype& o)
81    {
82       std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl;
83       std::swap(m_value, o.m_value);
84    }
strboost::multiprecision::concepts::number_backend_float_architype85    std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
86    {
87       std::stringstream ss;
88       ss.flags(f);
89       if(digits)
90          ss.precision(digits);
91       else
92          ss.precision(std::numeric_limits<long double>::digits10 + 2);
93       boost::intmax_t i = m_value;
94       boost::uintmax_t u = m_value;
95       if(!(f & std::ios_base::scientific) && m_value == i)
96          ss << i;
97       else if(!(f & std::ios_base::scientific) && m_value == u)
98          ss << u;
99       else
100          ss << m_value;
101       std::string s = ss.str();
102       std::cout << "Converting to string (" << s << ")" << std::endl;
103       return s;
104    }
negateboost::multiprecision::concepts::number_backend_float_architype105    void negate()
106    {
107       std::cout << "Negating (" << m_value << ")" << std::endl;
108       m_value = -m_value;
109    }
compareboost::multiprecision::concepts::number_backend_float_architype110    int compare(const number_backend_float_architype& o)const
111    {
112       std::cout << "Comparison" << std::endl;
113       return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
114    }
compareboost::multiprecision::concepts::number_backend_float_architype115    int compare(boost::long_long_type i)const
116    {
117       std::cout << "Comparison with int" << std::endl;
118       return m_value > i ? 1 : (m_value < i ? -1 : 0);
119    }
compareboost::multiprecision::concepts::number_backend_float_architype120    int compare(boost::ulong_long_type i)const
121    {
122       std::cout << "Comparison with unsigned" << std::endl;
123       return m_value > i ? 1 : (m_value < i ? -1 : 0);
124    }
compareboost::multiprecision::concepts::number_backend_float_architype125    int compare(long double d)const
126    {
127       std::cout << "Comparison with long double" << std::endl;
128       return m_value > d ? 1 : (m_value < d ? -1 : 0);
129    }
130    long double m_value;
131 };
132 
eval_add(number_backend_float_architype & result,const number_backend_float_architype & o)133 inline void eval_add(number_backend_float_architype& result, const number_backend_float_architype& o)
134 {
135    std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl;
136    result.m_value += o.m_value;
137 }
eval_subtract(number_backend_float_architype & result,const number_backend_float_architype & o)138 inline void eval_subtract(number_backend_float_architype& result, const number_backend_float_architype& o)
139 {
140    std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl;
141    result.m_value -= o.m_value;
142 }
eval_multiply(number_backend_float_architype & result,const number_backend_float_architype & o)143 inline void eval_multiply(number_backend_float_architype& result, const number_backend_float_architype& o)
144 {
145    std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl;
146    result.m_value *= o.m_value;
147 }
eval_divide(number_backend_float_architype & result,const number_backend_float_architype & o)148 inline void eval_divide(number_backend_float_architype& result, const number_backend_float_architype& o)
149 {
150    std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl;
151    result.m_value /= o.m_value;
152 }
153 
eval_convert_to(boost::ulong_long_type * result,const number_backend_float_architype & val)154 inline void eval_convert_to(boost::ulong_long_type* result, const number_backend_float_architype& val)
155 {
156    *result = static_cast<boost::ulong_long_type>(val.m_value);
157 }
eval_convert_to(boost::long_long_type * result,const number_backend_float_architype & val)158 inline void eval_convert_to(boost::long_long_type* result, const number_backend_float_architype& val)
159 {
160    *result = static_cast<boost::long_long_type>(val.m_value);
161 }
eval_convert_to(long double * result,number_backend_float_architype & val)162 inline void eval_convert_to(long double* result, number_backend_float_architype& val)
163 {
164    *result = val.m_value;
165 }
166 
eval_frexp(number_backend_float_architype & result,const number_backend_float_architype & arg,int * exp)167 inline void eval_frexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int* exp)
168 {
169    result = std::frexp(arg.m_value, exp);
170 }
171 
eval_ldexp(number_backend_float_architype & result,const number_backend_float_architype & arg,int exp)172 inline void eval_ldexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int exp)
173 {
174    result = std::ldexp(arg.m_value, exp);
175 }
176 
eval_floor(number_backend_float_architype & result,const number_backend_float_architype & arg)177 inline void eval_floor(number_backend_float_architype& result, const number_backend_float_architype& arg)
178 {
179    result = std::floor(arg.m_value);
180 }
181 
eval_ceil(number_backend_float_architype & result,const number_backend_float_architype & arg)182 inline void eval_ceil(number_backend_float_architype& result, const number_backend_float_architype& arg)
183 {
184    result = std::ceil(arg.m_value);
185 }
186 
eval_sqrt(number_backend_float_architype & result,const number_backend_float_architype & arg)187 inline void eval_sqrt(number_backend_float_architype& result, const number_backend_float_architype& arg)
188 {
189    result = std::sqrt(arg.m_value);
190 }
191 
eval_fpclassify(const number_backend_float_architype & arg)192 inline int eval_fpclassify(const number_backend_float_architype& arg)
193 {
194    return (boost::math::fpclassify)(arg.m_value);
195 }
196 
197 typedef boost::multiprecision::number<number_backend_float_architype> mp_number_float_architype;
198 
199 } // namespace
200 
201 template<>
202 struct number_category<concepts::number_backend_float_architype> : public mpl::int_<number_kind_floating_point>{};
203 
204 }} // namespaces
205 
206 namespace std{
207 
208 template <boost::multiprecision::expression_template_option ExpressionTemplates>
209 class numeric_limits<boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype, ExpressionTemplates> > : public std::numeric_limits<long double>
210 {
211    typedef std::numeric_limits<long double> base_type;
212    typedef boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype, ExpressionTemplates> number_type;
213 public:
number_type(min)214    static number_type (min)() BOOST_NOEXCEPT { return (base_type::min)(); }
number_type(max)215    static number_type (max)() BOOST_NOEXCEPT { return (base_type::max)(); }
lowest()216    static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
epsilon()217    static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
round_error()218    static number_type round_error() BOOST_NOEXCEPT { return base_type::round_error(); }
infinity()219    static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
quiet_NaN()220    static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
signaling_NaN()221    static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
denorm_min()222    static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
223 };
224 
225 }
226 
227 #ifdef BOOST_MSVC
228 #pragma warning(pop)
229 #endif
230 
231 #endif
232