• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  Use, modification and distribution are subject to the
2 //  Boost Software License, Version 1.0. (See accompanying file
3 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4 
5 // Copyright Paul A. Bristow 2013
6 // Copyright Christopher Kormanyos 2013.
7 // Copyright John Maddock 2013.
8 
9 #ifdef _MSC_VER
10 #  pragma warning (disable : 4512)
11 #  pragma warning (disable : 4996)
12 #endif
13 
14 #define BOOST_TEST_MAIN
15 #define BOOST_LIB_DIAGNOSTIC "on"// Show library file details.
16 
17 
18 
19 //[expression_template_1
20 
21 #include <limits>
22 #include <iostream>
23 #include <boost/multiprecision/cpp_dec_float.hpp>
24 
25 #include <boost/test/tools/floating_point_comparison.hpp> // Extra test tool for FP comparison.
26 #include <boost/test/unit_test.hpp>
27 
28 
29 typedef boost::multiprecision::number<
30    boost::multiprecision::cpp_dec_float<50>,
31    boost::multiprecision::et_off> cpp_dec_float_50_noet;
32 
33 typedef boost::multiprecision::number<
34    boost::multiprecision::cpp_dec_float<50>,
35    boost::multiprecision::et_on> cpp_dec_float_50_et;
36 
37 
38 // there is no need for this anymore, however this could be defined by
39 // the user in order to support additional types for floating point
40 // comparison.
41 #if 0
42 namespace boost { namespace math { namespace fpc {
43 
44   template <class A, boost::multiprecision::expression_template_option B>
45   struct tolerance_based< boost::multiprecision::number<
46    A,
47    B > > : boost::mpl::true_ {};
48 
49   template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
50   struct tolerance_based<
51     boost::multiprecision::detail::expression<
52       tag, Arg1, Arg2, Arg3, Arg4> > : boost::mpl::true_ {};
53 
54 } } }
55 #endif
56 
57 
58 
59 
60 
61 /*`To define a 50 decimal digit type using `cpp_dec_float`,
62 you must pass two template parameters to `boost::multiprecision::number`.
63 
64 It may be more legible to use a two-staged type definition such as this:
65 
66 ``
67 typedef boost::multiprecision::cpp_dec_float<50> mp_backend;
68 typedef boost::multiprecision::number<mp_backend, boost::multiprecision::et_off> cpp_dec_float_50_noet;
69 ``
70 
71 Here, we first define `mp_backend` as `cpp_dec_float` with 50 digits.
72 The second step passes this backend to `boost::multiprecision::number`
73 with `boost::multiprecision::et_off`, an enumerated type.
74 
75   typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<50>, boost::multiprecision::et_off>
76   cpp_dec_float_50_noet;
77 
78 You can reduce typing with a `using` directive `using namespace boost::multiprecision;`
79 if desired, as shown below.
80 */
81 
82 using namespace boost::multiprecision;
83 
84 #if 0
85 BOOST_AUTO_TEST_CASE(multiprecision_types_are_arithmetic)
86 {
87   typedef number<cpp_dec_float<50>, et_off> cpp_dec_float_50_noet;
88   BOOST_TEST((std::numeric_limits<cpp_dec_float_50_noet>::is_specialized));
89 }
90 #endif
91 
92 
93 /*`Now `cpp_dec_float_50_noet` or `cpp_dec_float_50_et`
94 can be used as a direct replacement for built-in types like `double` etc.
95 */
96 
BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_noet)97 BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_noet)
98 { // No expression templates/
99   typedef number<cpp_dec_float<50>, et_off> cpp_dec_float_50_noet;
100 
101   std::cout.precision(std::numeric_limits<cpp_dec_float_50_noet>::digits10); // All significant digits.
102   std::cout << std::showpoint << std::endl; // Show trailing zeros.
103 
104   cpp_dec_float_50_noet a ("1.0");
105   cpp_dec_float_50_noet b ("1.0");
106   b += std::numeric_limits<cpp_dec_float_50_noet>::epsilon(); // Increment least significant decimal digit.
107 
108   cpp_dec_float_50_noet eps = std::numeric_limits<cpp_dec_float_50_noet>::epsilon();
109 
110   std::cout <<"a = " << a << ",\nb = " << b << ",\neps = " << eps << std::endl;
111 
112   BOOST_CHECK_CLOSE(a, b, eps * 100); // Expected to pass (because tolerance is as percent).
113   BOOST_CHECK_CLOSE_FRACTION(a, b, eps); // Expected to pass (because tolerance is as fraction).
114 
115 #ifndef BOOST_TEST_MACRO_LIMITED_SUPPORT
116   namespace tt = boost::test_tools;
117   BOOST_TEST( a == b, tt::tolerance( tt::fpc::percent_tolerance( eps * 100 ) ) );
118   BOOST_TEST( a == b, tt::tolerance( eps ) );
119 #endif
120 
121 //] [/expression_template_1]git
122 
123 } // BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
124 
BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_et)125 BOOST_AUTO_TEST_CASE(cpp_float_test_check_close_et)
126 { // Using expression templates.
127   typedef number<cpp_dec_float<50>, et_on> cpp_dec_float_50_et;
128 
129   std::cout.precision(std::numeric_limits<cpp_dec_float_50_et>::digits10); // All significant digits.
130   std::cout << std::showpoint << std::endl; // Show trailing zeros.
131 
132   cpp_dec_float_50_et a("1.0");
133   cpp_dec_float_50_et b("1.0");
134   b += std::numeric_limits<cpp_dec_float_50_et>::epsilon(); // Increment least significant decimal digit.
135 
136   cpp_dec_float_50_et eps = std::numeric_limits<cpp_dec_float_50_et>::epsilon();
137 
138   std::cout << "a = " << a << ",\nb = " << b << ",\neps = " << eps << std::endl;
139 
140   BOOST_CHECK_CLOSE(a, b, eps * 100); // Expected to pass (because tolerance is as percent).
141   BOOST_CHECK_CLOSE_FRACTION(a, b, eps); // Expected to pass (because tolerance is as fraction).
142 
143 #ifndef BOOST_TEST_MACRO_LIMITED_SUPPORT
144   namespace tt = boost::test_tools;
145   BOOST_TEST( a == b, tt::tolerance( tt::fpc::percent_tolerance<cpp_dec_float_50_et>( eps * 100 ) ) );
146   BOOST_TEST( a == b, tt::tolerance( eps ) );
147 #endif
148   /*`Using `cpp_dec_float_50` with the default expression template use switched on,
149   the compiler error message for `BOOST_CHECK_CLOSE_FRACTION(a, b, eps); would be:
150   */
151   // failure floating_point_comparison.hpp(59): error C2440: 'static_cast' :
152   // cannot convert from 'int' to 'boost::multiprecision::detail::expression<tag,Arg1,Arg2,Arg3,Arg4>'
153   //] [/expression_template_1]
154 
155 } // BOOST_AUTO_TEST_CASE(cpp_float_test_check_close)
156 
157 /*
158 
159 Output:
160 
161   Description: Autorun "J:\Cpp\big_number\Debug\test_cpp_float_close_fraction.exe"
162   Running 1 test case...
163 
164   a = 1.0000000000000000000000000000000000000000000000000,
165   b = 1.0000000000000000000000000000000000000000000000001,
166   eps = 1.0000000000000000000000000000000000000000000000000e-49
167 
168   *** No errors detected
169 
170 */
171