1 | // Boost.Units - A C++ library for zero-overhead dimensional analysis and |
---|---|
2 | // unit/quantity manipulation and conversion |
3 | // |
4 | // Copyright (C) 2014 Erik Erlandson |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. (See |
7 | // accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | |
10 | #include <iostream> |
11 | #include <sstream> |
12 | |
13 | #include <boost/units/quantity.hpp> |
14 | #include <boost/units/conversion.hpp> |
15 | #include <boost/units/io.hpp> |
16 | |
17 | #include <boost/units/systems/si/prefixes.hpp> |
18 | #include <boost/units/systems/si/time.hpp> |
19 | |
20 | // All information systems definitions |
21 | #include <boost/units/systems/information.hpp> |
22 | |
23 | using std::cout; |
24 | using std::cerr; |
25 | using std::endl; |
26 | using std::stringstream; |
27 | |
28 | namespace bu = boost::units; |
29 | namespace si = boost::units::si; |
30 | |
31 | using bu::quantity; |
32 | |
33 | using bu::information::bit_base_unit; |
34 | using bu::information::byte_base_unit; |
35 | using bu::information::nat_base_unit; |
36 | using bu::information::hartley_base_unit; |
37 | using bu::information::shannon_base_unit; |
38 | |
39 | |
40 | #include "test_close.hpp" |
41 | |
42 | #include <boost/multiprecision/cpp_int.hpp> |
43 | |
44 | const double close_fraction = 0.0000001; |
45 | |
46 | // checks that cf(u2,u1) == expected |
47 | // also checks invariant property that cf(u2,u1) * cf(u1,u2) == 1 |
48 | #define CHECK_DIRECT_CF(u1, u2, expected) \ |
49 | BOOST_UNITS_TEST_CLOSE(bu::conversion_factor((u2), (u1)), (expected), close_fraction); \ |
50 | BOOST_UNITS_TEST_CLOSE(bu::conversion_factor((u2), (u1)) * bu::conversion_factor((u1), (u2)), 1.0, close_fraction); |
51 | |
52 | // check transitive conversion factors |
53 | // invariant: cf(u1,u3) = cf(u1,u2)*cf(u2,u3) |
54 | #define CHECK_TRANSITIVE_CF(u1, u2, u3) { \ |
55 | BOOST_CONSTEXPR_OR_CONST double cf12 = bu::conversion_factor((u2), (u1)) ; \ |
56 | BOOST_CONSTEXPR_OR_CONST double cf23 = bu::conversion_factor((u3), (u2)) ; \ |
57 | BOOST_CONSTEXPR_OR_CONST double cf13 = bu::conversion_factor((u3), (u1)) ; \ |
58 | BOOST_UNITS_TEST_CLOSE(cf13, cf12*cf23, close_fraction); \ |
59 | BOOST_CONSTEXPR_OR_CONST double cf32 = bu::conversion_factor((u2), (u3)) ; \ |
60 | BOOST_CONSTEXPR_OR_CONST double cf21 = bu::conversion_factor((u1), (u2)) ; \ |
61 | BOOST_CONSTEXPR_OR_CONST double cf31 = bu::conversion_factor((u1), (u3)) ; \ |
62 | BOOST_UNITS_TEST_CLOSE(cf31, cf32*cf21, close_fraction); \ |
63 | } |
64 | |
65 | |
66 | void test_cf_bit_byte() { |
67 | CHECK_DIRECT_CF(bit_base_unit::unit_type(), byte_base_unit::unit_type(), 8.0); |
68 | } |
69 | |
70 | void test_cf_bit_nat() { |
71 | CHECK_DIRECT_CF(bit_base_unit::unit_type(), nat_base_unit::unit_type(), 1.442695040888964); |
72 | } |
73 | |
74 | void test_cf_bit_hartley() { |
75 | CHECK_DIRECT_CF(bit_base_unit::unit_type(), hartley_base_unit::unit_type(), 3.321928094887363); |
76 | } |
77 | |
78 | void test_cf_bit_shannon() { |
79 | CHECK_DIRECT_CF(bit_base_unit::unit_type(), shannon_base_unit::unit_type(), 1.0); |
80 | } |
81 | |
82 | ///////////////////////////////////////////////////////////////////////////////////// |
83 | // spot-check that these are automatically transitive, thru central "hub unit" bit: |
84 | // basic pattern is to test invariant property: cf(c,a) = cf(c,b)*cf(b,a) |
85 | |
86 | void test_transitive_byte_nat() { |
87 | CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), bit_base_unit::unit_type(), nat_base_unit::unit_type()); |
88 | } |
89 | void test_transitive_nat_hartley() { |
90 | CHECK_TRANSITIVE_CF(nat_base_unit::unit_type(), bit_base_unit::unit_type(), hartley_base_unit::unit_type()); |
91 | } |
92 | void test_transitive_hartley_shannon() { |
93 | CHECK_TRANSITIVE_CF(hartley_base_unit::unit_type(), bit_base_unit::unit_type(), shannon_base_unit::unit_type()); |
94 | } |
95 | void test_transitive_shannon_byte() { |
96 | CHECK_TRANSITIVE_CF(shannon_base_unit::unit_type(), bit_base_unit::unit_type(), byte_base_unit::unit_type()); |
97 | } |
98 | |
99 | // test transitive factors, none of which are bit, just for good measure |
100 | void test_transitive_byte_nat_hartley() { |
101 | CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), nat_base_unit::unit_type(), hartley_base_unit::unit_type()); |
102 | } |
103 | |
104 | void test_byte_quantity_is_default() { |
105 | using namespace bu::information; |
106 | using bu::information::byte; |
107 | BOOST_CONSTEXPR_OR_CONST quantity<info, double> qd(2 * byte); |
108 | BOOST_TEST_EQ(qd.value(), double(2)); |
109 | BOOST_CONSTEXPR_OR_CONST quantity<info, long> ql(2 * byte); |
110 | BOOST_TEST_EQ(ql.value(), long(2)); |
111 | } |
112 | |
113 | void test_byte_quantity_explicit() { |
114 | using namespace bu::information; |
115 | using bu::information::byte; |
116 | BOOST_CONSTEXPR_OR_CONST quantity<hu::byte::info, double> qd(2 * byte); |
117 | BOOST_TEST_EQ(qd.value(), double(2)); |
118 | BOOST_CONSTEXPR_OR_CONST quantity<hu::byte::info, long> ql(2 * byte); |
119 | BOOST_TEST_EQ(ql.value(), long(2)); |
120 | } |
121 | |
122 | void test_bit_quantity() { |
123 | using namespace bu::information; |
124 | BOOST_CONSTEXPR_OR_CONST quantity<hu::bit::info, double> qd(2 * bit); |
125 | BOOST_TEST_EQ(qd.value(), double(2)); |
126 | BOOST_CONSTEXPR_OR_CONST quantity<hu::bit::info, long> ql(2 * bit); |
127 | BOOST_TEST_EQ(ql.value(), long(2)); |
128 | } |
129 | |
130 | void test_nat_quantity() { |
131 | using namespace bu::information; |
132 | BOOST_CONSTEXPR_OR_CONST quantity<hu::nat::info, double> qd(2 * nat); |
133 | BOOST_TEST_EQ(qd.value(), double(2)); |
134 | BOOST_CONSTEXPR_OR_CONST quantity<hu::nat::info, long> ql(2 * nat); |
135 | BOOST_TEST_EQ(ql.value(), long(2)); |
136 | } |
137 | |
138 | void test_hartley_quantity() { |
139 | using namespace bu::information; |
140 | BOOST_CONSTEXPR_OR_CONST quantity<hu::hartley::info, double> qd(2 * hartley); |
141 | BOOST_TEST_EQ(qd.value(), double(2)); |
142 | BOOST_CONSTEXPR_OR_CONST quantity<hu::hartley::info, long> ql(2 * hartley); |
143 | BOOST_TEST_EQ(ql.value(), long(2)); |
144 | } |
145 | |
146 | void test_shannon_quantity() { |
147 | using namespace bu::information; |
148 | BOOST_CONSTEXPR_OR_CONST quantity<hu::shannon::info, double> qd(2 * shannon); |
149 | BOOST_TEST_EQ(qd.value(), double(2)); |
150 | BOOST_CONSTEXPR_OR_CONST quantity<hu::shannon::info, long> ql(2 * shannon); |
151 | BOOST_TEST_EQ(ql.value(), long(2)); |
152 | } |
153 | |
154 | void test_mixed_hu() { |
155 | using namespace bu::information; |
156 | BOOST_CONSTEXPR_OR_CONST double cf = 0.001; |
157 | BOOST_UNITS_TEST_CLOSE((quantity<hu::bit::info>(1.0 * bits)).value(), 1.0, cf); |
158 | BOOST_UNITS_TEST_CLOSE((quantity<hu::byte::info>(1.0 * bits)).value(), 1.0/8.0, cf); |
159 | BOOST_UNITS_TEST_CLOSE((quantity<hu::nat::info>(1.0 * bits)).value(), 0.69315, cf); |
160 | BOOST_UNITS_TEST_CLOSE((quantity<hu::hartley::info>(1.0 * bits)).value(), 0.30102, cf); |
161 | BOOST_UNITS_TEST_CLOSE((quantity<hu::shannon::info>(1.0 * bits)).value(), 1.0, cf); |
162 | } |
163 | |
164 | void test_info_prefixes() { |
165 | using namespace bu::information; |
166 | using bu::information::byte; |
167 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q10(1LL * kibi * byte); |
168 | BOOST_TEST_EQ(q10.value(), 1024LL); |
169 | |
170 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q20(1LL * mebi * byte); |
171 | BOOST_TEST_EQ(q20.value(), 1048576LL); |
172 | |
173 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q30(1LL * gibi * byte); |
174 | BOOST_TEST_EQ(q30.value(), 1073741824LL); |
175 | |
176 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q40(1LL * tebi * byte); |
177 | BOOST_TEST_EQ(q40.value(), 1099511627776LL); |
178 | |
179 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q50(1LL * pebi * byte); |
180 | BOOST_TEST_EQ(q50.value(), 1125899906842624LL); |
181 | |
182 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q60(1LL * exbi * byte); |
183 | BOOST_TEST_EQ(q60.value(), 1152921504606846976LL); |
184 | |
185 | using boost::multiprecision::int128_t; |
186 | |
187 | const quantity<info, int128_t> q70(1LL * zebi * byte); |
188 | BOOST_TEST_EQ(q70.value(), int128_t("1180591620717411303424")); |
189 | |
190 | const quantity<info, int128_t> q80(1LL * yobi * byte); |
191 | BOOST_TEST_EQ(q80.value(), int128_t("1208925819614629174706176")); |
192 | |
193 | // sanity check: si prefixes should also operate |
194 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q1e3(1LL * si::kilo * byte); |
195 | BOOST_TEST_EQ(q1e3.value(), 1000LL); |
196 | |
197 | BOOST_CONSTEXPR_OR_CONST quantity<info, long long> q1e6(1LL * si::mega * byte); |
198 | BOOST_TEST_EQ(q1e6.value(), 1000000LL); |
199 | } |
200 | |
201 | void test_unit_constant_io() { |
202 | using namespace bu::information; |
203 | |
204 | std::stringstream ss; |
205 | ss << bu::symbol_format << bytes; |
206 | BOOST_TEST_EQ(ss.str(), "B"); |
207 | |
208 | ss.str(s: ""); |
209 | ss << bu::name_format << bytes; |
210 | BOOST_TEST_EQ(ss.str(), "byte"); |
211 | |
212 | ss.str(s: ""); |
213 | ss << bu::symbol_format << bits; |
214 | BOOST_TEST_EQ(ss.str(), "b"); |
215 | |
216 | ss.str(s: ""); |
217 | ss << bu::name_format << bits; |
218 | BOOST_TEST_EQ(ss.str(), "bit"); |
219 | |
220 | ss.str(s: ""); |
221 | ss << bu::symbol_format << nats; |
222 | BOOST_TEST_EQ(ss.str(), "nat"); |
223 | |
224 | ss.str(s: ""); |
225 | ss << bu::name_format << nats; |
226 | BOOST_TEST_EQ(ss.str(), "nat"); |
227 | |
228 | ss.str(s: ""); |
229 | ss << bu::symbol_format << hartleys; |
230 | BOOST_TEST_EQ(ss.str(), "Hart"); |
231 | |
232 | ss.str(s: ""); |
233 | ss << bu::name_format << hartleys; |
234 | BOOST_TEST_EQ(ss.str(), "hartley"); |
235 | |
236 | ss.str(s: ""); |
237 | ss << bu::symbol_format << shannons; |
238 | BOOST_TEST_EQ(ss.str(), "Sh"); |
239 | |
240 | ss.str(s: ""); |
241 | ss << bu::name_format << shannons; |
242 | BOOST_TEST_EQ(ss.str(), "shannon"); |
243 | } |
244 | |
245 | int main() |
246 | { |
247 | test_cf_bit_byte(); |
248 | test_cf_bit_nat(); |
249 | test_cf_bit_hartley(); |
250 | test_cf_bit_shannon(); |
251 | test_transitive_byte_nat(); |
252 | test_transitive_nat_hartley(); |
253 | test_transitive_hartley_shannon(); |
254 | test_transitive_shannon_byte(); |
255 | test_transitive_byte_nat_hartley(); |
256 | test_byte_quantity_is_default(); |
257 | test_byte_quantity_explicit(); |
258 | test_bit_quantity(); |
259 | test_nat_quantity(); |
260 | test_hartley_quantity(); |
261 | test_shannon_quantity(); |
262 | test_mixed_hu(); |
263 | test_info_prefixes(); |
264 | test_unit_constant_io(); |
265 | return boost::report_errors(); |
266 | } |
267 |
Definitions
- close_fraction
- test_cf_bit_byte
- test_cf_bit_nat
- test_cf_bit_hartley
- test_cf_bit_shannon
- test_transitive_byte_nat
- test_transitive_nat_hartley
- test_transitive_hartley_shannon
- test_transitive_shannon_byte
- test_transitive_byte_nat_hartley
- test_byte_quantity_is_default
- test_byte_quantity_explicit
- test_bit_quantity
- test_nat_quantity
- test_hartley_quantity
- test_shannon_quantity
- test_mixed_hu
- test_info_prefixes
- test_unit_constant_io
Learn to use CMake with our Intro Training
Find out more