@@ -17,113 +17,7 @@ This example can be found in the `examples/` folder as https://github.com/cppall
1717
1818[source, c++]
1919----
20- // Copyright 2024 Matt Borland
21- // Distributed under the Boost Software License, Version 1.0.
22- // https://www.boost.org/LICENSE_1_0.txt
23- //
24- // This file demonstrates some of the very basic ways you con construct decimal types
25- // This includes: from integer; integer and exponent; integer exponent and sign; string
26-
27- #include <boost/decimal/decimal32_t.hpp> // For decimal32_t type
28- #include <boost/decimal/iostream.hpp> // For <iostream> support of decimal types
29- #include <boost/decimal/cmath.hpp> // For isnan and isinf
30- #include <string>
31- #include <iostream>
32-
33- int main()
34- {
35- using boost::decimal::decimal32_t; // The decimal32_t type
36- using boost::decimal::construction_sign; // An enum class for specifying sign during certain instances of construction
37- using boost::decimal::isinf; // Analogous to std::isinf but for decimal types
38- using boost::decimal::isnan; // Analogous to std::isnan but for decimal types
39-
40- // Construction from an integer
41- constexpr decimal32_t val_1 {100};
42-
43- // Construction from a signed integer and exponent
44- constexpr decimal32_t val_2 {10, 1};
45-
46- // Construction from an unsigned integer, exponent, and sign
47- // The sign enum is named construction_sign, and has two members: positive and negative
48- constexpr decimal32_t val_3 {1U, 2, construction_sign::negative};
49-
50- std::cout << "Val_1: " << val_1 << '\n'
51- << "Val_2: " << val_2 << '\n'
52- << "Val_3: " << val_3 << '\n';
53-
54- if (val_1 == val_2 && val_2 == val_3 && val_1 == val_3)
55- {
56- std::cout << "All equal values" << std::endl;
57- }
58-
59- // Demonstration of the overflow and underflow handling
60- // A value that overflows constructs an infinity (which can be queried using isinf)
61- // A value that underflows constructs a zero
62- constexpr decimal32_t overflow_value {100, 10000};
63- if (isinf(overflow_value))
64- {
65- std::cout << "Overflow constructs infinity" << std::endl;
66- }
67-
68- constexpr decimal32_t underflow_value {100, -10000};
69- constexpr decimal32_t zero {0};
70- if (underflow_value == zero)
71- {
72- std::cout << "Underflow constructs zero" << std::endl;
73- }
74-
75- // Construction of NANs can be done using numeric limits,
76- // and checked using the normal isnan function
77- constexpr decimal32_t non_finite_from_float {std::numeric_limits<decimal32_t>::quiet_NaN()};
78- if (isnan(non_finite_from_float))
79- {
80- std::cout << "NaN constructs NaN" << std::endl;
81- }
82-
83- // We can also construct both from a C-string (const char*) and from a std::string
84-
85- const char* c_string_value {"4.3e-02"};
86- const decimal32_t from_c_string {c_string_value};
87- const decimal32_t from_std_string {std::string(c_string_value)};
88-
89- if (from_c_string == from_std_string)
90- {
91- std::cout << "Values constructed from const char* and std::string are the same" << '\n';
92- }
93-
94- // If we attempt construction for a string that cannot be converted into a decimal value,
95- // the constructor will do 1 of 2 things:
96- // 1) In a noexcept environment the constructor will return a quiet NaN
97- // 2) Otherwise it will throw
98- //
99- // The exception environment is detected automatically,
100- // or can be set by defining BOOST_DECIMAL_DISABLE_EXCEPTIONS
101-
102- const char* bad_string {"Junk_String"};
103-
104- #ifndef BOOST_DECIMAL_DISABLE_EXCEPTIONS
105-
106- try
107- {
108- const decimal32_t throwing_value {bad_string};
109- std::cout << throwing_value << '\n';
110- }
111- catch (const std::runtime_error& e)
112- {
113- std::cout << e.what() << std::endl;
114- }
115-
116- #else
117-
118- const decimal32_t nan_value {bad_string};
119- if (isnan(nan_value))
120- {
121- std::cout << "Bad string construction has formed a NAN" << std::endl;
122- }
123-
124- #endif
125- }
126-
20+ include::example$basic_construction.cpp[]
12721----
12822
12923The expected output from this example is:
@@ -145,63 +39,9 @@ This example can be found in the `examples/` folder as https://github.com/cppall
14539
14640[source, c++]
14741----
148- // This file briefly demonstrates the results of mixed decimal comparisons and arithmetic
149-
150- #include <boost/decimal/decimal32_t.hpp> // For the type decimal32_t
151- #include <boost/decimal/decimal64_t.hpp> // For the type decimal64_t
152- #include <boost/decimal/iostream.hpp> // For decimal type support to <iostream>
153- #include <type_traits>
154- #include <iostream>
155-
156- int main()
157- {
158- using boost::decimal::decimal32_t;
159- using boost::decimal::decimal64_t;
160- using boost::decimal::decimal128_t;
161-
162- // First construct two values that we will perform arithmetic with
163- const decimal32_t a {"5.2"};
164- const decimal64_t b {"3.9"};
165-
166- std::cout << "decimal32_t value (a): " << a << '\n'
167- << "decimal64_t value (b): " << b << '\n';
168-
169- // Mixed decimal comparisons are allowed by default
170- if (a > b)
171- {
172- std::cout << "a is greater than b" << '\n';
173- }
174-
175- // Even comparison of unrepresentable values is fine
176- // For example decimal32_t can't represent decimal64_t max value
177- constexpr decimal64_t dec64_max {std::numeric_limits<decimal64_t>::max()};
178- if (a < dec64_max)
179- {
180- std::cout << a << " is less than " << dec64_max << '\n';
181- }
182-
183- // Danger awaits if you decide to do this yourself instead of letting the system do it for you,
184- // since in this example the two should compare equal but overflowing decimal32_t makes infinity
185- if (static_cast<decimal32_t>(dec64_max) < dec64_max)
186- {
187- std::cout << dec64_max << " is less than " << static_cast<decimal32_t>(dec64_max) << '\n';
188- }
189-
190- // With mixed operations like +, -, *, / we promote to the higher precision type
191- // Example: decimal32_t + decimal64_t -> decimal64_t
192-
193- // We use auto here for two reasons
194- // 1) To demonstrate that it's safe
195- // 2) To show the promotion with the conditional logic that follows
196- const auto c {a + b};
197- using c_type = std::remove_cv_t<decltype(c)>; // We used const auto so the result is const decimal64_t
198-
199- static_assert(std::is_same<c_type, decimal64_t>::value, "decimal32_t + decimal64_t is supposed to yield decimal64_t");
200- std::cout << "The result of a + b is a decimal64_t: " << c << '\n';
201-
202- return 0;
203- }
42+ include::example$promotion.cpp[]
20443----
44+
20545Expected Output:
20646----
20747decimal32_t value (a): 5.2
@@ -219,102 +59,9 @@ This example can be found in the `examples/` folder as https://github.com/cppall
21959
22060[source, c++]
22161----
222- // This file demonstrates the various ways that <charconv> support can be used with the decimal library
223- // NOTE: <charconv> need not be included to use this functionality
224-
225- #include <boost/decimal/decimal64_t.hpp> // For the type decimal64_t
226- #include <boost/decimal/charconv.hpp> // For <charconv> support
227- #include <boost/decimal/iostream.hpp> // For decimal support <iostream>
228- #include <iostream> // <iostream>
229- #include <cstring> // For std::strlen
230-
231- int main()
232- {
233- using boost::decimal::decimal64_t; // The type decimal64_t
234- using boost::decimal::to_chars; // The to_chars functions
235- using boost::decimal::to_chars_result; // The return type of to_chars
236- using boost::decimal::from_chars; // The from_chars functions
237- using boost::decimal::from_chars_result;// The return type of from_chars
238- using boost::decimal::chars_format; // The enum class of the different formatting options
239- using boost::decimal::formatting_limits;// Allows the user to correctly size buffers
240-
241- const char* initial_value {"-7.12345e+06"};
242-
243- decimal64_t initial_decimal;
244- const from_chars_result r_initial {from_chars(initial_value, initial_value + std::strlen(initial_value), initial_decimal)};
245-
246- // from_chars_result contains a value of std::errc, but also has a bool operator for better checks like this
247- // Regular <charconv> should be getting this bool operator in C++26
248- if (!r_initial)
249- {
250- // Here you can handle an error condition in any way you see fit
251- // For the purposes of our example we log and abort
252- std::cout << "Unexpected failure" << std::endl;
253- return 1;
254- }
255- else
256- {
257- std::cout << "Initial decimal: " << initial_decimal << '\n';
258- }
259-
260- // boost::decimal::from_chars deviates from the C++ standard by allowing a std::string,
261- // or a std::string_view (when available)
262- //
263- // It is also perfectly acceptable to use an auto return type for even more brevity when using from_chars
264- const std::string string_value {"3.1415"};
265- decimal64_t string_decimal;
266- const auto r_string {from_chars(string_value, string_decimal)};
267- if (r_string)
268- {
269- std::cout << "Value from string: " << string_decimal << '\n';
270- }
271-
272- // We can now compare the various ways to print the value
273- // First we will review the formatting_limits struct
274- // This struct contains a number of members that allow the to_chars buffer to be correctly sized
275- //
276- // First formatting_limits takes a type and optionally a precision as template parameters
277- // It then has members each corresponding to the maximum number of characters needed to print the type
278- //
279- // 1) scientific_format_max_chars
280- // 2) fixed_format_max_chars
281- // 3) hex_format_max_chars
282- // 4) cohort_preserving_scientific_max_chars
283- // 5) general_format_max_chars
284- // 6) max_chars - Equal to the maximum value of 1 to 5 to allow to_chars of any format
285- //
286- // Each of these will give you one additional character so you can write a null terminator to the end
287- // NOTE: to_chars IS NOT default null terminated
288-
289- char scientific_buffer[formatting_limits<decimal64_t>::scientific_format_max_chars];
290- const to_chars_result r_sci {to_chars(scientific_buffer,
291- scientific_buffer + sizeof(scientific_buffer), initial_decimal, chars_format::scientific)};
292- if (r_sci)
293- {
294- *r_sci.ptr = '\0'; // to_chars does not null terminate per the C++ standard
295- std::cout << "Value in scientific format: " << scientific_buffer << '\n';
296- }
297- // else handle the error how you would like
298-
299- // If we went to print the value to some specified precision our buffer will need more space
300- // Formatting limits takes a precision in this case
301- //
302- // Also as with from_chars it's perfectly fine to use an auto return type with to_chars
303- constexpr int required_precision {20};
304- char precision_20_scientific_buffer[formatting_limits<decimal64_t, required_precision>::scientific_format_max_chars];
305- const auto r_sci20 {to_chars(precision_20_scientific_buffer,
306- precision_20_scientific_buffer + sizeof(precision_20_scientific_buffer),
307- initial_decimal, chars_format::scientific, required_precision)};
308-
309- if (r_sci20)
310- {
311- *r_sci20.ptr = '\0';
312- std::cout << "Value in scientific format with precision 20: " << precision_20_scientific_buffer << '\n';
313- }
314- // else handle the error how you would like
315- }
316-
62+ include::example$charconv.cpp[]
31763----
64+
31865Output:
31966----
32067Initial decimal: -7123450
@@ -330,57 +77,10 @@ This example can be found in the `examples/` folder as https://github.com/cppall
33077
33178[source, c++]
33279----
333- #include <boost/decimal/decimal32_t.hpp> // For type decimal32_t
334- #include <boost/decimal/decimal64_t.hpp> // For type decimal64_t
335- #include <boost/decimal/decimal128_t.hpp> // For type decimal128_t
336- #include <boost/decimal/iostream.hpp> // For <iostream> support
337- #include <boost/decimal/cmath.hpp> // For sin function
338- #include <iostream>
339- #include <cmath>
340-
341- template <typename T>
342- void sin_identity(T val)
343- {
344- // ADL allows builtin and decimal types to both be used
345- // Boost.Decimal is not allowed to overload std::sin so it must be provided in its own namespace
346- // You must also include using std::sin to ensure that it is found for the float, double, and long double cases.
347- // It is preferred to have using statements for the functions you intend to use instead of using namespace XXX.
348- using std::sin;
349- using boost::decimal::sin;
350-
351- // sin(x) = -sin(-x)
352- // The call here MUST be unqualified, or you will get compiler errors
353- // For example calling std::sin here would not allow any of the decimal types to be used
354- std::cout << "sin(" << val << ") = " << sin(val) << '\n'
355- << "-sin(" << -val << ") = " << -sin(-val) << "\n\n";
356- }
357-
358- int main()
359- {
360- // Because of the two using statements in the above function we can now call it with built-in floating point,
361- // or our decimal types as show below
362-
363- std::cout << "Float:\n";
364- sin_identity(-0.5F);
365-
366- std::cout << "Double:\n";
367- sin_identity(-0.5);
368-
369- std::cout << "Long Double:\n";
370- sin_identity(-0.5L);
371-
372- std::cout << "decimal32_t:\n";
373- sin_identity(boost::decimal::decimal32_t{"-0.5"});
374-
375- std::cout << "decimal64_t:\n";
376- sin_identity(boost::decimal::decimal64_t{"-0.5"});
377-
378- std::cout << "decimal128_t:\n";
379- sin_identity(boost::decimal::decimal128_t{"-0.5"});
380- }
80+ include::example$adl.cpp[]
38181----
38282
383- The expected output of this is :
83+ Expected Output :
38484----
38585Float:
38686sin(-0.5) = -0.479426
0 commit comments