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// Test real concept.
7
8// real_concept is an archetype for User defined Real types.
9
10// This file defines the features, constructors, operators, functions...
11// that are essential to use mathematical and statistical functions.
12// The template typename "RealType" is used where this type
13// (as well as the normal built-in types, float, double & long double)
14// can be used.
15// That this is the minimum set is confirmed by use as a type
16// in tests of all functions & distributions, for example:
17// test_spots(0.F); & test_spots(0.); for float and double, but also
18// test_spots(boost::math::concepts::real_concept(0.));
19// NTL quad_float type is an example of a type meeting the requirements,
20// but note minor additions are needed - see ntl.diff and documentation
21// "Using With NTL - a High-Precision Floating-Point Library".
22
23#ifndef BOOST_MATH_REAL_CONCEPT_HPP
24#define BOOST_MATH_REAL_CONCEPT_HPP
25
26#include <boost/math/special_functions/round.hpp>
27#include <boost/math/special_functions/trunc.hpp>
28#include <boost/math/special_functions/modf.hpp>
29#include <boost/math/tools/big_constant.hpp>
30#include <boost/math/tools/precision.hpp>
31#include <boost/math/tools/config.hpp>
32#include <boost/math/policies/policy.hpp>
33#include <boost/math/special_functions/asinh.hpp>
34#include <boost/math/special_functions/atanh.hpp>
35#if defined(__SGI_STL_PORT)
36# include <boost/math/tools/real_cast.hpp>
37#endif
38#include <ostream>
39#include <istream>
40#include <limits>
41#include <cmath>
42#include <cstdint>
43
44#if defined(__SGI_STL_PORT) || defined(_RWSTD_VER) || defined(__LIBCOMO__)
45# include <cstdio>
46#endif
47
48#if defined __has_include
49# if __cplusplus > 202002L || _MSVC_LANG > 202002L
50# if __has_include (<stdfloat>)
51# include <stdfloat>
52# endif
53# endif
54#endif
55
56namespace boost{ namespace math{
57
58namespace concepts
59{
60
61#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
62 typedef double real_concept_base_type;
63#else
64 typedef long double real_concept_base_type;
65#endif
66
67class real_concept
68{
69public:
70 // Constructors:
71 real_concept() : m_value(0){}
72 real_concept(char c) : m_value(c){}
73 real_concept(wchar_t c) : m_value(c){}
74 real_concept(unsigned char c) : m_value(c){}
75 real_concept(signed char c) : m_value(c){}
76 real_concept(unsigned short c) : m_value(c){}
77 real_concept(short c) : m_value(c){}
78 real_concept(unsigned int c) : m_value(c){}
79 real_concept(int c) : m_value(c){}
80 real_concept(unsigned long c) : m_value(c){}
81 real_concept(long c) : m_value(c){}
82 real_concept(unsigned long long c) : m_value(static_cast<real_concept_base_type>(c)){}
83 real_concept(long long c) : m_value(static_cast<real_concept_base_type>(c)){}
84 real_concept(float c) : m_value(c){}
85 real_concept(double c) : m_value(c){}
86 real_concept(long double c) : m_value(c){}
87#ifdef BOOST_MATH_USE_FLOAT128
88 real_concept(BOOST_MATH_FLOAT128_TYPE c) : m_value(c){}
89#endif
90#ifdef __STDCPP_FLOAT32_T__
91 real_concept(std::float32_t c) : m_value(static_cast<real_concept_base_type>(c)){}
92#endif
93#ifdef __STDCPP_FLOAT64_T__
94 real_concept(std::float64_t c) : m_value(static_cast<real_concept_base_type>(c)){}
95#endif
96
97 // Assignment:
98 real_concept& operator=(char c) { m_value = c; return *this; }
99 real_concept& operator=(unsigned char c) { m_value = c; return *this; }
100 real_concept& operator=(signed char c) { m_value = c; return *this; }
101 real_concept& operator=(wchar_t c) { m_value = c; return *this; }
102 real_concept& operator=(short c) { m_value = c; return *this; }
103 real_concept& operator=(unsigned short c) { m_value = c; return *this; }
104 real_concept& operator=(int c) { m_value = c; return *this; }
105 real_concept& operator=(unsigned int c) { m_value = c; return *this; }
106 real_concept& operator=(long c) { m_value = c; return *this; }
107 real_concept& operator=(unsigned long c) { m_value = c; return *this; }
108 real_concept& operator=(long long c) { m_value = static_cast<real_concept_base_type>(c); return *this; }
109 real_concept& operator=(unsigned long long c) { m_value = static_cast<real_concept_base_type>(c); return *this; }
110 real_concept& operator=(float c) { m_value = c; return *this; }
111 real_concept& operator=(double c) { m_value = c; return *this; }
112 real_concept& operator=(long double c) { m_value = c; return *this; }
113 #ifdef __STDCPP_FLOAT32_T__
114 real_concept& operator=(std::float32_t c) { m_value = c; return *this; }
115 #endif
116 #ifdef __STDCPP_FLOAT64_T__
117 real_concept& operator=(std::float64_t c) { m_value = c; return *this; }
118 #endif
119
120 // Access:
121 real_concept_base_type value()const{ return m_value; }
122
123 // Member arithmetic:
124 real_concept& operator+=(const real_concept& other)
125 { m_value += other.value(); return *this; }
126 real_concept& operator-=(const real_concept& other)
127 { m_value -= other.value(); return *this; }
128 real_concept& operator*=(const real_concept& other)
129 { m_value *= other.value(); return *this; }
130 real_concept& operator/=(const real_concept& other)
131 { m_value /= other.value(); return *this; }
132 real_concept operator-()const
133 { return -m_value; }
134 real_concept const& operator+()const
135 { return *this; }
136 real_concept& operator++()
137 { ++m_value; return *this; }
138 real_concept& operator--()
139 { --m_value; return *this; }
140
141private:
142 real_concept_base_type m_value;
143};
144
145// Non-member arithmetic:
146inline real_concept operator+(const real_concept& a, const real_concept& b)
147{
148 real_concept result(a);
149 result += b;
150 return result;
151}
152inline real_concept operator-(const real_concept& a, const real_concept& b)
153{
154 real_concept result(a);
155 result -= b;
156 return result;
157}
158inline real_concept operator*(const real_concept& a, const real_concept& b)
159{
160 real_concept result(a);
161 result *= b;
162 return result;
163}
164inline real_concept operator/(const real_concept& a, const real_concept& b)
165{
166 real_concept result(a);
167 result /= b;
168 return result;
169}
170
171// Comparison:
172inline bool operator == (const real_concept& a, const real_concept& b)
173{ return a.value() == b.value(); }
174inline bool operator != (const real_concept& a, const real_concept& b)
175{ return a.value() != b.value();}
176inline bool operator < (const real_concept& a, const real_concept& b)
177{ return a.value() < b.value(); }
178inline bool operator <= (const real_concept& a, const real_concept& b)
179{ return a.value() <= b.value(); }
180inline bool operator > (const real_concept& a, const real_concept& b)
181{ return a.value() > b.value(); }
182inline bool operator >= (const real_concept& a, const real_concept& b)
183{ return a.value() >= b.value(); }
184
185// Non-member functions:
186inline real_concept acos(real_concept a)
187{ return std::acos(x: a.value()); }
188inline real_concept cos(real_concept a)
189{ return std::cos(x: a.value()); }
190inline real_concept asin(real_concept a)
191{ return std::asin(x: a.value()); }
192inline real_concept atan(real_concept a)
193{ return std::atan(x: a.value()); }
194inline real_concept atan2(real_concept a, real_concept b)
195{ return std::atan2(y: a.value(), x: b.value()); }
196inline real_concept ceil(real_concept a)
197{ return std::ceil(x: a.value()); }
198#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
199// I've seen std::fmod(long double) crash on some platforms
200// so use fmodl instead:
201#ifdef _WIN32_WCE
202//
203// Ugly workaround for macro fmodl:
204//
205inline long double call_fmodl(long double a, long double b)
206{ return fmodl(a, b); }
207inline real_concept fmod(real_concept a, real_concept b)
208{ return call_fmodl(a.value(), b.value()); }
209#else
210inline real_concept fmod(real_concept a, real_concept b)
211{ return fmodl(x: a.value(), y: b.value()); }
212#endif
213#endif
214inline real_concept cosh(real_concept a)
215{ return std::cosh(x: a.value()); }
216inline real_concept exp(real_concept a)
217{ return std::exp(x: a.value()); }
218inline real_concept fabs(real_concept a)
219{ return std::fabs(x: a.value()); }
220inline real_concept abs(real_concept a)
221{ return std::abs(x: a.value()); }
222inline real_concept floor(real_concept a)
223{ return std::floor(x: a.value()); }
224inline real_concept modf(real_concept a, real_concept* ipart)
225{
226#ifdef __MINGW32__
227 real_concept_base_type ip;
228 real_concept_base_type result = boost::math::modf(a.value(), &ip);
229 *ipart = ip;
230 return result;
231#else
232 real_concept_base_type ip;
233 real_concept_base_type result = std::modf(x: a.value(), iptr: &ip);
234 *ipart = ip;
235 return result;
236#endif
237}
238inline real_concept frexp(real_concept a, int* expon)
239{ return std::frexp(x: a.value(), exp: expon); }
240inline real_concept ldexp(real_concept a, int expon)
241{ return std::ldexp(x: a.value(), exp: expon); }
242inline real_concept log(real_concept a)
243{ return std::log(x: a.value()); }
244inline real_concept log10(real_concept a)
245{ return std::log10(x: a.value()); }
246inline real_concept tan(real_concept a)
247{ return std::tan(x: a.value()); }
248inline real_concept pow(real_concept a, real_concept b)
249{ return std::pow(x: a.value(), y: b.value()); }
250#if !defined(__SUNPRO_CC)
251inline real_concept pow(real_concept a, int b)
252{ return std::pow(x: a.value(), y: b); }
253#else
254inline real_concept pow(real_concept a, int b)
255{ return std::pow(a.value(), static_cast<real_concept_base_type>(b)); }
256#endif
257inline real_concept sin(real_concept a)
258{ return std::sin(x: a.value()); }
259inline real_concept sinh(real_concept a)
260{ return std::sinh(x: a.value()); }
261inline real_concept sqrt(real_concept a)
262{ return std::sqrt(x: a.value()); }
263inline real_concept tanh(real_concept a)
264{ return std::tanh(x: a.value()); }
265
266//
267// C++11 ism's
268// Note that these must not actually call the std:: versions as that precludes using this
269// header to test in C++03 mode, call the Boost versions instead:
270//
271inline boost::math::concepts::real_concept asinh(boost::math::concepts::real_concept a)
272{
273 return boost::math::asinh(x: a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
274}
275inline boost::math::concepts::real_concept acosh(boost::math::concepts::real_concept a)
276{
277 return boost::math::acosh(x: a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
278}
279inline boost::math::concepts::real_concept atanh(boost::math::concepts::real_concept a)
280{
281 return boost::math::atanh(x: a.value(), boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::ignore_error>()));
282}
283
284//
285// Conversion and truncation routines:
286//
287template <class Policy>
288inline int iround(const concepts::real_concept& v, const Policy& pol)
289{ return boost::math::iround(v.value(), pol); }
290inline int iround(const concepts::real_concept& v)
291{ return boost::math::iround(v: v.value(), pol: policies::policy<>()); }
292template <class Policy>
293inline long lround(const concepts::real_concept& v, const Policy& pol)
294{ return boost::math::lround(v.value(), pol); }
295inline long lround(const concepts::real_concept& v)
296{ return boost::math::lround(v: v.value(), pol: policies::policy<>()); }
297
298template <class Policy>
299inline long long llround(const concepts::real_concept& v, const Policy& pol)
300{ return boost::math::llround(v.value(), pol); }
301inline long long llround(const concepts::real_concept& v)
302{ return boost::math::llround(v: v.value(), pol: policies::policy<>()); }
303
304template <class Policy>
305inline int itrunc(const concepts::real_concept& v, const Policy& pol)
306{ return boost::math::itrunc(v.value(), pol); }
307inline int itrunc(const concepts::real_concept& v)
308{ return boost::math::itrunc(v: v.value(), pol: policies::policy<>()); }
309template <class Policy>
310inline long ltrunc(const concepts::real_concept& v, const Policy& pol)
311{ return boost::math::ltrunc(v.value(), pol); }
312inline long ltrunc(const concepts::real_concept& v)
313{ return boost::math::ltrunc(v: v.value(), pol: policies::policy<>()); }
314
315template <class Policy>
316inline long long lltrunc(const concepts::real_concept& v, const Policy& pol)
317{ return boost::math::lltrunc(v.value(), pol); }
318inline long long lltrunc(const concepts::real_concept& v)
319{ return boost::math::lltrunc(v: v.value(), pol: policies::policy<>()); }
320
321// Streaming:
322template <class charT, class traits>
323inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const real_concept& a)
324{
325 return os << a.value();
326}
327template <class charT, class traits>
328inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, real_concept& a)
329{
330 real_concept_base_type v;
331 is >> v;
332 a = v;
333 return is;
334}
335
336} // namespace concepts
337
338namespace tools
339{
340
341template <>
342inline concepts::real_concept make_big_value<concepts::real_concept>(boost::math::tools::largest_float val, const char* , std::false_type const&, std::false_type const&)
343{
344 return val; // Can't use lexical_cast here, sometimes it fails....
345}
346
347template <>
348inline concepts::real_concept max_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
349{
350 return max_value<concepts::real_concept_base_type>();
351}
352
353template <>
354inline concepts::real_concept min_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
355{
356 return min_value<concepts::real_concept_base_type>();
357}
358
359template <>
360inline concepts::real_concept log_max_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
361{
362 return log_max_value<concepts::real_concept_base_type>();
363}
364
365template <>
366inline concepts::real_concept log_min_value<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
367{
368 return log_min_value<concepts::real_concept_base_type>();
369}
370
371template <>
372inline concepts::real_concept epsilon<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept))
373{
374#ifdef __SUNPRO_CC
375 return std::numeric_limits<concepts::real_concept_base_type>::epsilon();
376#else
377 return tools::epsilon<concepts::real_concept_base_type>();
378#endif
379}
380
381template <>
382inline constexpr int digits<concepts::real_concept>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(concepts::real_concept)) noexcept
383{
384 // Assume number of significand bits is same as real_concept_base_type,
385 // unless std::numeric_limits<T>::is_specialized to provide digits.
386 return tools::digits<concepts::real_concept_base_type>();
387 // Note that if numeric_limits real concept is NOT specialized to provide digits10
388 // (or max_digits10) then the default precision of 6 decimal digits will be used
389 // by Boost test (giving misleading error messages like
390 // "difference between {9.79796} and {9.79796} exceeds 5.42101e-19%"
391 // and by Boost lexical cast and serialization causing loss of accuracy.
392}
393
394} // namespace tools
395} // namespace math
396} // namespace boost
397
398#endif // BOOST_MATH_REAL_CONCEPT_HPP
399
400
401

source code of boost/libs/math/include/boost/math/concepts/real_concept.hpp