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