1 //  Copyright John Maddock 2006.
2 //  Use, modification and distribution are subject to the
3 //  Boost Software License, Version 1.0. (See accompanying file
4 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // std_real_concept is an archetype for built-in Real types.
7 
8 // The main purpose in providing this type is to verify
9 // that std lib functions are found via a using declaration
10 // bringing those functions into the current scope, and not
11 // just because they happen to be in global scope.
12 //
13 // If ::pow is found rather than std::pow say, then the code
14 // will silently compile, but truncation of long doubles to
15 // double will cause a significant loss of precision.
16 // A template instantiated with std_real_concept will *only*
17 // compile if it std::whatever is in scope.
18 
19 #include <boost/config.hpp>
20 #include <boost/limits.hpp>
21 #include <boost/math/policies/policy.hpp>
22 #include <boost/math/special_functions/math_fwd.hpp>
23 
24 #include <ostream>
25 #include <istream>
26 #include <boost/config/no_tr1/cmath.hpp>
27 #include <math.h> // fmodl
28 
29 #ifndef BOOST_MATH_STD_REAL_CONCEPT_HPP
30 #define BOOST_MATH_STD_REAL_CONCEPT_HPP
31 
32 namespace boost{ namespace math{
33 
34 namespace concepts
35 {
36 
37 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
38    typedef double std_real_concept_base_type;
39 #else
40    typedef long double std_real_concept_base_type;
41 #endif
42 
43 class std_real_concept
44 {
45 public:
46    // Constructors:
std_real_concept()47    std_real_concept() : m_value(0){}
std_real_concept(char c)48    std_real_concept(char c) : m_value(c){}
49 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
std_real_concept(wchar_t c)50    std_real_concept(wchar_t c) : m_value(c){}
51 #endif
std_real_concept(unsigned char c)52    std_real_concept(unsigned char c) : m_value(c){}
std_real_concept(signed char c)53    std_real_concept(signed char c) : m_value(c){}
std_real_concept(unsigned short c)54    std_real_concept(unsigned short c) : m_value(c){}
std_real_concept(short c)55    std_real_concept(short c) : m_value(c){}
std_real_concept(unsigned int c)56    std_real_concept(unsigned int c) : m_value(c){}
std_real_concept(int c)57    std_real_concept(int c) : m_value(c){}
std_real_concept(unsigned long c)58    std_real_concept(unsigned long c) : m_value(c){}
std_real_concept(long c)59    std_real_concept(long c) : m_value(c){}
60 #if defined(__DECCXX) || defined(__SUNPRO_CC)
std_real_concept(unsigned long long c)61    std_real_concept(unsigned long long c) : m_value(static_cast<std_real_concept_base_type>(c)){}
std_real_concept(long long c)62    std_real_concept(long long c) : m_value(static_cast<std_real_concept_base_type>(c)){}
63 #elif defined(BOOST_HAS_LONG_LONG)
std_real_concept(boost::ulong_long_type c)64    std_real_concept(boost::ulong_long_type c) : m_value(static_cast<std_real_concept_base_type>(c)){}
std_real_concept(boost::long_long_type c)65    std_real_concept(boost::long_long_type c) : m_value(static_cast<std_real_concept_base_type>(c)){}
66 #endif
std_real_concept(float c)67    std_real_concept(float c) : m_value(c){}
std_real_concept(double c)68    std_real_concept(double c) : m_value(c){}
std_real_concept(long double c)69    std_real_concept(long double c) : m_value(c){}
70 #ifdef BOOST_MATH_USE_FLOAT128
std_real_concept(BOOST_MATH_FLOAT128_TYPE c)71    std_real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){}
72 #endif
73 
74    // Assignment:
operator =(char c)75    std_real_concept& operator=(char c) { m_value = c; return *this; }
operator =(unsigned char c)76    std_real_concept& operator=(unsigned char c) { m_value = c; return *this; }
operator =(signed char c)77    std_real_concept& operator=(signed char c) { m_value = c; return *this; }
78 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
operator =(wchar_t c)79    std_real_concept& operator=(wchar_t c) { m_value = c; return *this; }
80 #endif
operator =(short c)81    std_real_concept& operator=(short c) { m_value = c; return *this; }
operator =(unsigned short c)82    std_real_concept& operator=(unsigned short c) { m_value = c; return *this; }
operator =(int c)83    std_real_concept& operator=(int c) { m_value = c; return *this; }
operator =(unsigned int c)84    std_real_concept& operator=(unsigned int c) { m_value = c; return *this; }
operator =(long c)85    std_real_concept& operator=(long c) { m_value = c; return *this; }
operator =(unsigned long c)86    std_real_concept& operator=(unsigned long c) { m_value = c; return *this; }
87 #if defined(__DECCXX) || defined(__SUNPRO_CC)
operator =(unsigned long long c)88    std_real_concept& operator=(unsigned long long c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
operator =(long long c)89    std_real_concept& operator=(long long c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
90 #elif defined(BOOST_HAS_LONG_LONG)
operator =(boost::long_long_type c)91    std_real_concept& operator=(boost::long_long_type c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
operator =(boost::ulong_long_type c)92    std_real_concept& operator=(boost::ulong_long_type c) { m_value = static_cast<std_real_concept_base_type>(c); return *this; }
93 #endif
operator =(float c)94    std_real_concept& operator=(float c) { m_value = c; return *this; }
operator =(double c)95    std_real_concept& operator=(double c) { m_value = c; return *this; }
operator =(long double c)96    std_real_concept& operator=(long double c) { m_value = c; return *this; }
97 
98    // Access:
value() const99    std_real_concept_base_type value()const{ return m_value; }
100 
101    // Member arithmetic:
operator +=(const std_real_concept & other)102    std_real_concept& operator+=(const std_real_concept& other)
103    { m_value += other.value(); return *this; }
operator -=(const std_real_concept & other)104    std_real_concept& operator-=(const std_real_concept& other)
105    { m_value -= other.value(); return *this; }
operator *=(const std_real_concept & other)106    std_real_concept& operator*=(const std_real_concept& other)
107    { m_value *= other.value(); return *this; }
operator /=(const std_real_concept & other)108    std_real_concept& operator/=(const std_real_concept& other)
109    { m_value /= other.value(); return *this; }
operator -() const110    std_real_concept operator-()const
111    { return -m_value; }
operator +() const112    std_real_concept const& operator+()const
113    { return *this; }
114 
115 private:
116    std_real_concept_base_type m_value;
117 };
118 
119 // Non-member arithmetic:
operator +(const std_real_concept & a,const std_real_concept & b)120 inline std_real_concept operator+(const std_real_concept& a, const std_real_concept& b)
121 {
122    std_real_concept result(a);
123    result += b;
124    return result;
125 }
operator -(const std_real_concept & a,const std_real_concept & b)126 inline std_real_concept operator-(const std_real_concept& a, const std_real_concept& b)
127 {
128    std_real_concept result(a);
129    result -= b;
130    return result;
131 }
operator *(const std_real_concept & a,const std_real_concept & b)132 inline std_real_concept operator*(const std_real_concept& a, const std_real_concept& b)
133 {
134    std_real_concept result(a);
135    result *= b;
136    return result;
137 }
operator /(const std_real_concept & a,const std_real_concept & b)138 inline std_real_concept operator/(const std_real_concept& a, const std_real_concept& b)
139 {
140    std_real_concept result(a);
141    result /= b;
142    return result;
143 }
144 
145 // Comparison:
operator ==(const std_real_concept & a,const std_real_concept & b)146 inline bool operator == (const std_real_concept& a, const std_real_concept& b)
147 { return a.value() == b.value(); }
operator !=(const std_real_concept & a,const std_real_concept & b)148 inline bool operator != (const std_real_concept& a, const std_real_concept& b)
149 { return a.value() != b.value();}
operator <(const std_real_concept & a,const std_real_concept & b)150 inline bool operator < (const std_real_concept& a, const std_real_concept& b)
151 { return a.value() < b.value(); }
operator <=(const std_real_concept & a,const std_real_concept & b)152 inline bool operator <= (const std_real_concept& a, const std_real_concept& b)
153 { return a.value() <= b.value(); }
operator >(const std_real_concept & a,const std_real_concept & b)154 inline bool operator > (const std_real_concept& a, const std_real_concept& b)
155 { return a.value() > b.value(); }
operator >=(const std_real_concept & a,const std_real_concept & b)156 inline bool operator >= (const std_real_concept& a, const std_real_concept& b)
157 { return a.value() >= b.value(); }
158 
159 } // namespace concepts
160 } // namespace math
161 } // namespace boost
162 
163 namespace std{
164 
165 // Non-member functions:
acos(boost::math::concepts::std_real_concept a)166 inline boost::math::concepts::std_real_concept acos(boost::math::concepts::std_real_concept a)
167 { return std::acos(a.value()); }
cos(boost::math::concepts::std_real_concept a)168 inline boost::math::concepts::std_real_concept cos(boost::math::concepts::std_real_concept a)
169 { return std::cos(a.value()); }
asin(boost::math::concepts::std_real_concept a)170 inline boost::math::concepts::std_real_concept asin(boost::math::concepts::std_real_concept a)
171 { return std::asin(a.value()); }
atan(boost::math::concepts::std_real_concept a)172 inline boost::math::concepts::std_real_concept atan(boost::math::concepts::std_real_concept a)
173 { return std::atan(a.value()); }
atan2(boost::math::concepts::std_real_concept a,boost::math::concepts::std_real_concept b)174 inline boost::math::concepts::std_real_concept atan2(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
175 { return std::atan2(a.value(), b.value()); }
ceil(boost::math::concepts::std_real_concept a)176 inline boost::math::concepts::std_real_concept ceil(boost::math::concepts::std_real_concept a)
177 { return std::ceil(a.value()); }
178 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
fmod(boost::math::concepts::std_real_concept a,boost::math::concepts::std_real_concept b)179 inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
180 { return fmodl(a.value(), b.value()); }
181 #else
fmod(boost::math::concepts::std_real_concept a,boost::math::concepts::std_real_concept b)182 inline boost::math::concepts::std_real_concept fmod(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
183 { return std::fmod(a.value(), b.value()); }
184 #endif
cosh(boost::math::concepts::std_real_concept a)185 inline boost::math::concepts::std_real_concept cosh(boost::math::concepts::std_real_concept a)
186 { return std::cosh(a.value()); }
exp(boost::math::concepts::std_real_concept a)187 inline boost::math::concepts::std_real_concept exp(boost::math::concepts::std_real_concept a)
188 { return std::exp(a.value()); }
fabs(boost::math::concepts::std_real_concept a)189 inline boost::math::concepts::std_real_concept fabs(boost::math::concepts::std_real_concept a)
190 { return std::fabs(a.value()); }
abs(boost::math::concepts::std_real_concept a)191 inline boost::math::concepts::std_real_concept abs(boost::math::concepts::std_real_concept a)
192 { return std::abs(a.value()); }
floor(boost::math::concepts::std_real_concept a)193 inline boost::math::concepts::std_real_concept floor(boost::math::concepts::std_real_concept a)
194 { return std::floor(a.value()); }
modf(boost::math::concepts::std_real_concept a,boost::math::concepts::std_real_concept * ipart)195 inline boost::math::concepts::std_real_concept modf(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept* ipart)
196 {
197    boost::math::concepts::std_real_concept_base_type ip;
198    boost::math::concepts::std_real_concept_base_type result = std::modf(a.value(), &ip);
199    *ipart = ip;
200    return result;
201 }
frexp(boost::math::concepts::std_real_concept a,int * expon)202 inline boost::math::concepts::std_real_concept frexp(boost::math::concepts::std_real_concept a, int* expon)
203 { return std::frexp(a.value(), expon); }
ldexp(boost::math::concepts::std_real_concept a,int expon)204 inline boost::math::concepts::std_real_concept ldexp(boost::math::concepts::std_real_concept a, int expon)
205 { return std::ldexp(a.value(), expon); }
log(boost::math::concepts::std_real_concept a)206 inline boost::math::concepts::std_real_concept log(boost::math::concepts::std_real_concept a)
207 { return std::log(a.value()); }
log10(boost::math::concepts::std_real_concept a)208 inline boost::math::concepts::std_real_concept log10(boost::math::concepts::std_real_concept a)
209 { return std::log10(a.value()); }
tan(boost::math::concepts::std_real_concept a)210 inline boost::math::concepts::std_real_concept tan(boost::math::concepts::std_real_concept a)
211 { return std::tan(a.value()); }
pow(boost::math::concepts::std_real_concept a,boost::math::concepts::std_real_concept b)212 inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
213 { return std::pow(a.value(), b.value()); }
214 #if !defined(__SUNPRO_CC)
pow(boost::math::concepts::std_real_concept a,int b)215 inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b)
216 { return std::pow(a.value(), b); }
217 #else
pow(boost::math::concepts::std_real_concept a,int b)218 inline boost::math::concepts::std_real_concept pow(boost::math::concepts::std_real_concept a, int b)
219 { return std::pow(a.value(), static_cast<long double>(b)); }
220 #endif
sin(boost::math::concepts::std_real_concept a)221 inline boost::math::concepts::std_real_concept sin(boost::math::concepts::std_real_concept a)
222 { return std::sin(a.value()); }
sinh(boost::math::concepts::std_real_concept a)223 inline boost::math::concepts::std_real_concept sinh(boost::math::concepts::std_real_concept a)
224 { return std::sinh(a.value()); }
sqrt(boost::math::concepts::std_real_concept a)225 inline boost::math::concepts::std_real_concept sqrt(boost::math::concepts::std_real_concept a)
226 { return std::sqrt(a.value()); }
tanh(boost::math::concepts::std_real_concept a)227 inline boost::math::concepts::std_real_concept tanh(boost::math::concepts::std_real_concept a)
228 { return std::tanh(a.value()); }
std_real_concept(nextafter)229 inline boost::math::concepts::std_real_concept (nextafter)(boost::math::concepts::std_real_concept a, boost::math::concepts::std_real_concept b)
230 { return (boost::math::nextafter)(a, b); }
231 //
232 // C++11 ism's
233 // Note that these must not actually call the std:: versions as that precludes using this
234 // header to test in C++03 mode, call the Boost versions instead:
235 //
asinh(boost::math::concepts::std_real_concept a)236 inline boost::math::concepts::std_real_concept asinh(boost::math::concepts::std_real_concept a)
237 { return boost::math::asinh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>())); }
acosh(boost::math::concepts::std_real_concept a)238 inline boost::math::concepts::std_real_concept acosh(boost::math::concepts::std_real_concept a)
239 { return boost::math::acosh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>())); }
atanh(boost::math::concepts::std_real_concept a)240 inline boost::math::concepts::std_real_concept atanh(boost::math::concepts::std_real_concept a)
241 { return boost::math::atanh(a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>())); }
242 inline bool (isfinite)(boost::math::concepts::std_real_concept a)
243 {
244    return (boost::math::isfinite)(a.value());
245 }
246 
247 
248 } // namespace std
249 
250 #include <boost/math/special_functions/round.hpp>
251 #include <boost/math/special_functions/trunc.hpp>
252 #include <boost/math/special_functions/modf.hpp>
253 #include <boost/math/tools/precision.hpp>
254 
255 namespace boost{ namespace math{ namespace concepts{
256 
257 //
258 // Conversion and truncation routines:
259 //
260 template <class Policy>
iround(const concepts::std_real_concept & v,const Policy & pol)261 inline int iround(const concepts::std_real_concept& v, const Policy& pol)
262 {
263    return boost::math::iround(v.value(), pol);
264 }
iround(const concepts::std_real_concept & v)265 inline int iround(const concepts::std_real_concept& v)
266 {
267    return boost::math::iround(v.value(), policies::policy<>());
268 }
269 
270 template <class Policy>
lround(const concepts::std_real_concept & v,const Policy & pol)271 inline long lround(const concepts::std_real_concept& v, const Policy& pol)
272 {
273    return boost::math::lround(v.value(), pol);
274 }
lround(const concepts::std_real_concept & v)275 inline long lround(const concepts::std_real_concept& v)
276 {
277    return boost::math::lround(v.value(), policies::policy<>());
278 }
279 
280 #ifdef BOOST_HAS_LONG_LONG
281 
282 template <class Policy>
llround(const concepts::std_real_concept & v,const Policy & pol)283 inline boost::long_long_type llround(const concepts::std_real_concept& v, const Policy& pol)
284 {
285    return boost::math::llround(v.value(), pol);
286 }
llround(const concepts::std_real_concept & v)287 inline boost::long_long_type llround(const concepts::std_real_concept& v)
288 {
289    return boost::math::llround(v.value(), policies::policy<>());
290 }
291 
292 #endif
293 
294 template <class Policy>
itrunc(const concepts::std_real_concept & v,const Policy & pol)295 inline int itrunc(const concepts::std_real_concept& v, const Policy& pol)
296 {
297    return boost::math::itrunc(v.value(), pol);
298 }
itrunc(const concepts::std_real_concept & v)299 inline int itrunc(const concepts::std_real_concept& v)
300 {
301    return boost::math::itrunc(v.value(), policies::policy<>());
302 }
303 
304 template <class Policy>
ltrunc(const concepts::std_real_concept & v,const Policy & pol)305 inline long ltrunc(const concepts::std_real_concept& v, const Policy& pol)
306 {
307    return boost::math::ltrunc(v.value(), pol);
308 }
ltrunc(const concepts::std_real_concept & v)309 inline long ltrunc(const concepts::std_real_concept& v)
310 {
311    return boost::math::ltrunc(v.value(), policies::policy<>());
312 }
313 
314 #ifdef BOOST_HAS_LONG_LONG
315 
316 template <class Policy>
lltrunc(const concepts::std_real_concept & v,const Policy & pol)317 inline boost::long_long_type lltrunc(const concepts::std_real_concept& v, const Policy& pol)
318 {
319    return boost::math::lltrunc(v.value(), pol);
320 }
lltrunc(const concepts::std_real_concept & v)321 inline boost::long_long_type lltrunc(const concepts::std_real_concept& v)
322 {
323    return boost::math::lltrunc(v.value(), policies::policy<>());
324 }
325 
326 #endif
327 
328 // Streaming:
329 template <class charT, class traits>
operator <<(std::basic_ostream<charT,traits> & os,const std_real_concept & a)330 inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const std_real_concept& a)
331 {
332    return os << a.value();
333 }
334 template <class charT, class traits>
operator >>(std::basic_istream<charT,traits> & is,std_real_concept & a)335 inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, std_real_concept& a)
336 {
337 #if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__) || defined(_LIBCPP_VERSION)
338    std::string s;
339    std_real_concept_base_type d;
340    is >> s;
341    std::sscanf(s.c_str(), "%Lf", &d);
342    a = d;
343    return is;
344 #else
345    std_real_concept_base_type v;
346    is >> v;
347    a = v;
348    return is;
349 #endif
350 }
351 
352 } // namespace concepts
353 }}
354 
355 #include <boost/math/tools/precision.hpp>
356 #include <boost/math/tools/big_constant.hpp>
357 
358 namespace boost{ namespace math{
359 namespace tools
360 {
361 
362 template <>
make_big_value(boost::math::tools::largest_float val,const char *,boost::false_type const &,boost::false_type const &)363 inline concepts::std_real_concept make_big_value<concepts::std_real_concept>(boost::math::tools::largest_float val, const char*, boost::false_type const&, boost::false_type const&)
364 {
365    return val;  // Can't use lexical_cast here, sometimes it fails....
366 }
367 
368 template <>
max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))369 inline concepts::std_real_concept max_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
370 {
371    return max_value<concepts::std_real_concept_base_type>();
372 }
373 
374 template <>
min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))375 inline concepts::std_real_concept min_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
376 {
377    return min_value<concepts::std_real_concept_base_type>();
378 }
379 
380 template <>
log_max_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))381 inline concepts::std_real_concept log_max_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
382 {
383    return log_max_value<concepts::std_real_concept_base_type>();
384 }
385 
386 template <>
log_min_value(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))387 inline concepts::std_real_concept log_min_value<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
388 {
389    return log_min_value<concepts::std_real_concept_base_type>();
390 }
391 
392 template <>
epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))393 inline concepts::std_real_concept epsilon(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept))
394 {
395    return tools::epsilon<concepts::std_real_concept_base_type>();
396 }
397 
398 template <>
digits(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC (concepts::std_real_concept))399 inline BOOST_MATH_CONSTEXPR int digits<concepts::std_real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::std_real_concept)) BOOST_NOEXCEPT
400 { // Assume number of significand bits is same as std_real_concept_base_type,
401   // unless std::numeric_limits<T>::is_specialized to provide digits.
402    return digits<concepts::std_real_concept_base_type>();
403 }
404 
405 template <>
real_cast(concepts::std_real_concept r)406 inline double real_cast<double, concepts::std_real_concept>(concepts::std_real_concept r)
407 {
408    return static_cast<double>(r.value());
409 }
410 
411 
412 } // namespace tools
413 
414 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
415 using concepts::itrunc;
416 using concepts::ltrunc;
417 using concepts::lltrunc;
418 using concepts::iround;
419 using concepts::lround;
420 using concepts::llround;
421 #endif
422 
423 } // namespace math
424 } // namespace boost
425 
426 //
427 // These must go at the end, as they include stuff that won't compile until
428 // after std_real_concept has been defined:
429 //
430 #include <boost/math/special_functions/acosh.hpp>
431 #include <boost/math/special_functions/asinh.hpp>
432 #include <boost/math/special_functions/atanh.hpp>
433 
434 #endif // BOOST_MATH_STD_REAL_CONCEPT_HPP
435