1 // numbers.cpp: example program to use C++20 <numbers> high precision constants
2 //
3 // Copyright (C) 2017-2021 Stillwater Supercomputing, Inc.
4 //
5 // This file is part of the universal numbers project, which is released under an MIT Open Source license.
6 #include <universal/utility/directives.hpp>
7 #include <limits>
8 #if (__cplusplus == 202003L) || (_MSVC_LANG == 202003L)
9 #include <numbers>    // high-precision numbers
10 #endif
11 #include <universal/utility/number_system_properties.hpp> //minmax_range etc. for native types
12 
13 // select the number systems we would like to compare
14 #include <universal/number/integer/integer.hpp>
15 #include <universal/number/fixpnt/fixpnt.hpp>
16 #include <universal/number/areal/areal.hpp>
17 #include <universal/number/cfloat/cfloat.hpp>
18 #include <universal/number/posit/posit.hpp>
19 #include <universal/number/lns/lns.hpp>
20 
21 #include <cstddef>
22 #include <stdexcept>
23 #include <cstring>
24 #include <ostream>
25 
26 #ifndef _MSC_VER
27 #  if __cplusplus < 201103
28 #    define CONSTEXPR11_TN
29 #    define CONSTEXPR14_TN
30 #    define CONSTEXPR17_TN
31 #    define NOEXCEPT_TN
32 #  elif __cplusplus < 201402
33 #    define CONSTEXPR11_TN constexpr
34 #    define CONSTEXPR14_TN
35 #    define CONSTEXPR17_TN
36 #    define NOEXCEPT_TN noexcept
37 #  else
38 #    define CONSTEXPR11_TN constexpr
39 #    define CONSTEXPR14_TN constexpr
40 #    define CONSTEXPR17_TN constexpr
41 #    define NOEXCEPT_TN noexcept
42 #  endif
43 #else  // _MSC_VER
44 #  if _MSC_VER < 1900
45 #    define CONSTEXPR11_TN
46 #    define CONSTEXPR14_TN
47 #    define NOEXCEPT_TN
48 #  elif _MSC_VER < 2000
49 #    define CONSTEXPR11_TN constexpr
50 #    define CONSTEXPR14_TN
51 #    define NOEXCEPT_TN noexcept
52 #  else
53 #    define CONSTEXPR11_TN constexpr
54 #    define CONSTEXPR14_TN constexpr
55 #    define NOEXCEPT_TN noexcept
56 #  endif
57 #endif  // _MSC_VER
58 
59 class static_string
60 {
61 	const char* const p_;
62 	const std::size_t sz_;
63 
64 public:
65 	typedef const char* const_iterator;
66 
67 	template <std::size_t N>
static_string(const char (& a)[N])68 	CONSTEXPR11_TN static_string(const char(&a)[N]) NOEXCEPT_TN
69 		: p_(a)
70 		, sz_(N - 1)
71 	{}
72 
static_string(const char * p,std::size_t N)73 	CONSTEXPR11_TN static_string(const char* p, std::size_t N) NOEXCEPT_TN
74 		: p_(p)
75 		, sz_(N)
76 	{}
77 
data() const78 	CONSTEXPR11_TN const char* data() const NOEXCEPT_TN { return p_; }
size() const79 	CONSTEXPR11_TN std::size_t size() const NOEXCEPT_TN { return sz_; }
80 
begin() const81 	CONSTEXPR11_TN const_iterator begin() const NOEXCEPT_TN { return p_; }
end() const82 	CONSTEXPR11_TN const_iterator end()   const NOEXCEPT_TN { return p_ + sz_; }
83 
operator [](std::size_t n) const84 	CONSTEXPR11_TN char operator[](std::size_t n) const
85 	{
86 		return n < sz_ ? p_[n] : throw std::out_of_range("static_string");
87 	}
88 };
89 
90 inline
91 std::ostream&
operator <<(std::ostream & os,static_string const & s)92 operator<<(std::ostream& os, static_string const& s)
93 {
94 	return os.write(s.data(), static_cast<std::streamsize>(s.size()));
95 }
96 
97 template <class T>
98 CONSTEXPR14_TN
99 static_string
type_name()100 type_name()
101 {
102 #ifdef __clang__
103 	static_string p = __PRETTY_FUNCTION__;
104 	return static_string(p.data() + 31, p.size() - 31 - 1);
105 #elif defined(__GNUC__)
106 	static_string p = __PRETTY_FUNCTION__;
107 #  if __cplusplus < 201402
108 	return static_string(p.data() + 36, p.size() - 36 - 1);
109 #  else
110 	return static_string(p.data() + 46, p.size() - 46 - 1);
111 #  endif
112 #elif defined(_MSC_VER)
113 	static_string p = __FUNCSIG__;
114 	return static_string(p.data() + 38, p.size() - 38 - 7);
115 #endif
116 }
117 
118 
main()119 int main()
120 try {
121 	using namespace sw::universal;
122 
123 	std::cout << "high-precision constants\n";
124 
125 	report_compiler_environment();
126 
127 	using int32    = integer<32>;
128 	using fixpnt32 = fixpnt<32,16>;
129 	using posit32  = posit<32,2>;
130 	using cfloat32 = cfloat<32, 8,uint8_t>;
131 	using areal32  = areal<32,8,uint32_t>; // should use a uint32_t for efficiency
132 	using lns32    = lns<32>;
133 
134 	// report on precision and dynamic range of the number system
135 
136 	std::streamsize precision = std::cout.precision();
137 
138 	constexpr size_t columnWidth = 30;
139 	numberTraits<int32, columnWidth>(std::cout);
140 	numberTraits<fixpnt32, columnWidth>(std::cout);
141 	numberTraits<float, columnWidth>(std::cout);
142 	numberTraits<cfloat32, columnWidth>(std::cout);
143 	numberTraits<areal32, columnWidth>(std::cout);
144 	numberTraits<posit32, columnWidth>(std::cout);
145 	numberTraits<lns32, columnWidth>(std::cout);
146 
147 	std::cout << "a better type name: " << type_tag(posit32()) << '\n';
148 
149 	std::cout << minmax_range<float>() << '\n';
150 	std::cout << minmax_range<posit32>() << '\n';
151 	std::cout << minmax_range<lns32>() << '\n';
152 
153 	std::cout << dynamic_range<float>() << '\n';
154 	std::cout << dynamic_range<posit32>() << '\n';
155 	std::cout << dynamic_range<lns32>() << '\n';
156 
157 	std::cout << symmetry<float>() << '\n';
158 	std::cout << symmetry<posit32>() << '\n';
159 	std::cout << symmetry<lns32>() << '\n';
160 
161 	compareNumberTraits<float, cfloat32>(std::cout);
162 	compareNumberTraits<float, posit32>(std::cout);
163 	compareNumberTraits<float, lns32>(std::cout);
164 
165 #if (__cplusplus == 202003L) || (_MSVC_LANG == 202003L)
166 	constexpr long double pi     = 3.14159265358979323846;
167 	//constexpr long double e      = 2.71828182845904523536;
168 	//constexpr long double log_2e = 1.44269504088896340736;
169 
170 	cout << std::setprecision(50);
171 	cout << "my pi             " << pi << endl;
172 	cout << "numbers::pi       " << std::numbers::pi << endl;   // a double constexpr
173 	cout << "pi_v<float>       " << std::numbers::pi_v<float> << endl;
174 	cout << "pi_v<double>      " << std::numbers::pi_v<double> << endl;
175 	cout << "pi_v<long double> " << std::numbers::pi_v<long double> << endl;
176 #endif
177 
178 	std::cout << std::setprecision(precision);
179 	std::cout << std::endl;
180 
181 	return EXIT_SUCCESS;
182 }
183 catch (char const* msg) {
184 	std::cerr << "Caught exception: " << msg << std::endl;
185 	return EXIT_FAILURE;
186 }
187 catch (const std::runtime_error& err) {
188 	std::cerr << "Caught runtime exception: " << err.what() << std::endl;
189 	return EXIT_FAILURE;
190 }
191 catch (...) {
192 	std::cerr << "Caught unknown exception" << std::endl;
193 	return EXIT_FAILURE;
194 }
195