1 // Boost.Units - A C++ library for zero-overhead dimensional analysis and
2 // unit/quantity manipulation and conversion
4 // Copyright (C) 2014 Erik Erlandson
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)
13 #include <boost/units/quantity.hpp>
14 #include <boost/units/conversion.hpp>
15 #include <boost/units/io.hpp>
17 #include <boost/units/systems/si/prefixes.hpp>
18 #include <boost/units/systems/si/time.hpp>
20 // All information systems definitions
21 #include <boost/units/systems/information.hpp>
26 using std::stringstream
;
28 namespace bu
= boost::units
;
29 namespace si
= boost::units::si
;
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
;
40 #define BOOST_TEST_MAIN
41 #include <boost/test/unit_test.hpp>
44 #include <boost/multiprecision/cpp_int.hpp>
46 const double close_fraction
= 0.0000001;
48 // checks that cf(u2,u1) == expected
49 // also checks invariant property that cf(u2,u1) * cf(u1,u2) == 1
50 #define CHECK_DIRECT_CF(u1, u2, expected) \
51 BOOST_CHECK_CLOSE_FRACTION(bu::conversion_factor((u2), (u1)), (expected), close_fraction); \
52 BOOST_CHECK_CLOSE_FRACTION(bu::conversion_factor((u2), (u1)) * bu::conversion_factor((u1), (u2)), 1.0, close_fraction);
54 // check transitive conversion factors
55 // invariant: cf(u1,u3) = cf(u1,u2)*cf(u2,u3)
56 #define CHECK_TRANSITIVE_CF(u1, u2, u3) { \
57 double cf12 = bu::conversion_factor((u2), (u1)) ; \
58 double cf23 = bu::conversion_factor((u3), (u2)) ; \
59 double cf13 = bu::conversion_factor((u3), (u1)) ; \
60 BOOST_CHECK_CLOSE_FRACTION(cf13, cf12*cf23, close_fraction); \
61 double cf32 = bu::conversion_factor((u2), (u3)) ; \
62 double cf21 = bu::conversion_factor((u1), (u2)) ; \
63 double cf31 = bu::conversion_factor((u1), (u3)) ; \
64 BOOST_CHECK_CLOSE_FRACTION(cf31, cf32*cf21, close_fraction); \
68 BOOST_AUTO_TEST_CASE(test_cf_bit_byte
) {
69 CHECK_DIRECT_CF(bit_base_unit::unit_type(), byte_base_unit::unit_type(), 8.0);
72 BOOST_AUTO_TEST_CASE(test_cf_bit_nat
) {
73 CHECK_DIRECT_CF(bit_base_unit::unit_type(), nat_base_unit::unit_type(), 1.442695040888964);
76 BOOST_AUTO_TEST_CASE(test_cf_bit_hartley
) {
77 CHECK_DIRECT_CF(bit_base_unit::unit_type(), hartley_base_unit::unit_type(), 3.321928094887363);
80 BOOST_AUTO_TEST_CASE(test_cf_bit_shannon
) {
81 CHECK_DIRECT_CF(bit_base_unit::unit_type(), shannon_base_unit::unit_type(), 1.0);
84 /////////////////////////////////////////////////////////////////////////////////////
85 // spot-check that these are automatically transitive, thru central "hub unit" bit:
86 // basic pattern is to test invariant property: cf(c,a) = cf(c,b)*cf(b,a)
88 BOOST_AUTO_TEST_CASE(test_transitive_byte_nat
) {
89 CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), bit_base_unit::unit_type(), nat_base_unit::unit_type());
91 BOOST_AUTO_TEST_CASE(test_transitive_nat_hartley
) {
92 CHECK_TRANSITIVE_CF(nat_base_unit::unit_type(), bit_base_unit::unit_type(), hartley_base_unit::unit_type());
94 BOOST_AUTO_TEST_CASE(test_transitive_hartley_shannon
) {
95 CHECK_TRANSITIVE_CF(hartley_base_unit::unit_type(), bit_base_unit::unit_type(), shannon_base_unit::unit_type());
97 BOOST_AUTO_TEST_CASE(test_transitive_shannon_byte
) {
98 CHECK_TRANSITIVE_CF(shannon_base_unit::unit_type(), bit_base_unit::unit_type(), byte_base_unit::unit_type());
101 // test transitive factors, none of which are bit, just for good measure
102 BOOST_AUTO_TEST_CASE(test_transitive_byte_nat_hartley
) {
103 CHECK_TRANSITIVE_CF(byte_base_unit::unit_type(), nat_base_unit::unit_type(), hartley_base_unit::unit_type());
106 BOOST_AUTO_TEST_CASE(test_byte_quantity_is_default
) {
107 using namespace bu::information
;
108 quantity
<info
, double> qd(2 * byte
);
109 BOOST_CHECK_EQUAL(qd
.value(), double(2));
110 quantity
<info
, long> ql(2 * byte
);
111 BOOST_CHECK_EQUAL(ql
.value(), long(2));
114 BOOST_AUTO_TEST_CASE(test_byte_quantity_explicit
) {
115 using namespace bu::information
;
116 quantity
<hu::byte::info
, double> qd(2 * byte
);
117 BOOST_CHECK_EQUAL(qd
.value(), double(2));
118 quantity
<hu::byte::info
, long> ql(2 * byte
);
119 BOOST_CHECK_EQUAL(ql
.value(), long(2));
122 BOOST_AUTO_TEST_CASE(test_bit_quantity
) {
123 using namespace bu::information
;
124 quantity
<hu::bit::info
, double> qd(2 * bit
);
125 BOOST_CHECK_EQUAL(qd
.value(), double(2));
126 quantity
<hu::bit::info
, long> ql(2 * bit
);
127 BOOST_CHECK_EQUAL(ql
.value(), long(2));
130 BOOST_AUTO_TEST_CASE(test_nat_quantity
) {
131 using namespace bu::information
;
132 quantity
<hu::nat::info
, double> qd(2 * nat
);
133 BOOST_CHECK_EQUAL(qd
.value(), double(2));
134 quantity
<hu::nat::info
, long> ql(2 * nat
);
135 BOOST_CHECK_EQUAL(ql
.value(), long(2));
138 BOOST_AUTO_TEST_CASE(test_hartley_quantity
) {
139 using namespace bu::information
;
140 quantity
<hu::hartley::info
, double> qd(2 * hartley
);
141 BOOST_CHECK_EQUAL(qd
.value(), double(2));
142 quantity
<hu::hartley::info
, long> ql(2 * hartley
);
143 BOOST_CHECK_EQUAL(ql
.value(), long(2));
146 BOOST_AUTO_TEST_CASE(test_shannon_quantity
) {
147 using namespace bu::information
;
148 quantity
<hu::shannon::info
, double> qd(2 * shannon
);
149 BOOST_CHECK_EQUAL(qd
.value(), double(2));
150 quantity
<hu::shannon::info
, long> ql(2 * shannon
);
151 BOOST_CHECK_EQUAL(ql
.value(), long(2));
154 BOOST_AUTO_TEST_CASE(test_mixed_hu
) {
155 using namespace bu::information
;
156 const double cf
= 0.001;
157 BOOST_CHECK_CLOSE_FRACTION((quantity
<hu::bit::info
>(1.0 * bits
)).value(), 1.0, cf
);
158 BOOST_CHECK_CLOSE_FRACTION((quantity
<hu::byte::info
>(1.0 * bits
)).value(), 1.0/8.0, cf
);
159 BOOST_CHECK_CLOSE_FRACTION((quantity
<hu::nat::info
>(1.0 * bits
)).value(), 0.69315, cf
);
160 BOOST_CHECK_CLOSE_FRACTION((quantity
<hu::hartley::info
>(1.0 * bits
)).value(), 0.30102, cf
);
161 BOOST_CHECK_CLOSE_FRACTION((quantity
<hu::shannon::info
>(1.0 * bits
)).value(), 1.0, cf
);
164 BOOST_AUTO_TEST_CASE(test_info_prefixes
) {
165 using namespace bu::information
;
166 quantity
<info
, long long> q10(1LL * kibi
* byte
);
167 BOOST_CHECK_EQUAL(q10
.value(), 1024LL);
169 quantity
<info
, long long> q20(1LL * mebi
* byte
);
170 BOOST_CHECK_EQUAL(q20
.value(), 1048576LL);
172 quantity
<info
, long long> q30(1LL * gibi
* byte
);
173 BOOST_CHECK_EQUAL(q30
.value(), 1073741824LL);
175 quantity
<info
, long long> q40(1LL * tebi
* byte
);
176 BOOST_CHECK_EQUAL(q40
.value(), 1099511627776LL);
178 quantity
<info
, long long> q50(1LL * pebi
* byte
);
179 BOOST_CHECK_EQUAL(q50
.value(), 1125899906842624LL);
181 quantity
<info
, long long> q60(1LL * exbi
* byte
);
182 BOOST_CHECK_EQUAL(q60
.value(), 1152921504606846976LL);
184 using boost::multiprecision::int128_t
;
186 quantity
<info
, int128_t
> q70(1LL * zebi
* byte
);
187 BOOST_CHECK_EQUAL(q70
.value(), int128_t("1180591620717411303424"));
189 quantity
<info
, int128_t
> q80(1LL * yobi
* byte
);
190 BOOST_CHECK_EQUAL(q80
.value(), int128_t("1208925819614629174706176"));
192 // sanity check: si prefixes should also operate
193 quantity
<info
, long long> q1e3(1LL * si::kilo
* byte
);
194 BOOST_CHECK_EQUAL(q1e3
.value(), 1000LL);
196 quantity
<info
, long long> q1e6(1LL * si::mega
* byte
);
197 BOOST_CHECK_EQUAL(q1e6
.value(), 1000000LL);
200 BOOST_AUTO_TEST_CASE(test_unit_constant_io
) {
201 using namespace bu::information
;
203 std::stringstream ss
;
204 ss
<< bu::symbol_format
<< bytes
;
205 BOOST_CHECK_EQUAL(ss
.str(), "B");
208 ss
<< bu::name_format
<< bytes
;
209 BOOST_CHECK_EQUAL(ss
.str(), "byte");
212 ss
<< bu::symbol_format
<< bits
;
213 BOOST_CHECK_EQUAL(ss
.str(), "b");
216 ss
<< bu::name_format
<< bits
;
217 BOOST_CHECK_EQUAL(ss
.str(), "bit");
220 ss
<< bu::symbol_format
<< nats
;
221 BOOST_CHECK_EQUAL(ss
.str(), "nat");
224 ss
<< bu::name_format
<< nats
;
225 BOOST_CHECK_EQUAL(ss
.str(), "nat");
228 ss
<< bu::symbol_format
<< hartleys
;
229 BOOST_CHECK_EQUAL(ss
.str(), "Hart");
232 ss
<< bu::name_format
<< hartleys
;
233 BOOST_CHECK_EQUAL(ss
.str(), "hartley");
236 ss
<< bu::symbol_format
<< shannons
;
237 BOOST_CHECK_EQUAL(ss
.str(), "Sh");
240 ss
<< bu::name_format
<< shannons
;
241 BOOST_CHECK_EQUAL(ss
.str(), "shannon");