diff --git a/Jamfile b/Jamfile index 56f60ddd..46af9f49 100644 --- a/Jamfile +++ b/Jamfile @@ -8,9 +8,9 @@ project histogram : requirements - gcc:"-std=c++14 -pedantic -Wall -Wextra" - clang:"-std=c++14 -pedantic -Wall -Wextra" - darwin:"-std=c++14 -pedantic -Wall -Wextra" + gcc:"-std=c++14 -Wall -Wextra -Wno-noexcept-type" + clang:"-std=c++14 -Wall -Wextra" + darwin:"-std=c++14 -Wall -Wextra" ; build-project test ; diff --git a/test/axis_regular_test.cpp b/test/axis_regular_test.cpp new file mode 100644 index 00000000..fee1173b --- /dev/null +++ b/test/axis_regular_test.cpp @@ -0,0 +1,158 @@ +// Copyright 2015-2017 Hans Dembinski +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "utility.hpp" + +using namespace boost::histogram; + +int main() { + // bad_ctors + { + BOOST_TEST_THROWS(axis::regular<>(0, 0, 1), std::invalid_argument); + } + + // axis::regular + { + axis::regular<> a{4, -2, 2}; + BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits::infinity()); + BOOST_TEST_EQ(a[a.size()].upper(), std::numeric_limits::infinity()); + axis::regular<> b; + BOOST_TEST_NE(a, b); + b = a; + BOOST_TEST_EQ(a, b); + b = b; + BOOST_TEST_EQ(a, b); + axis::regular<> c = std::move(b); + BOOST_TEST_EQ(c, a); + axis::regular<> d; + BOOST_TEST_NE(c, d); + d = std::move(c); + BOOST_TEST_EQ(d, a); + BOOST_TEST_EQ(a(-10.), -1); + BOOST_TEST_EQ(a(-2.1), -1); + BOOST_TEST_EQ(a(-2.0), 0); + BOOST_TEST_EQ(a(-1.1), 0); + BOOST_TEST_EQ(a(0.0), 2); + BOOST_TEST_EQ(a(0.9), 2); + BOOST_TEST_EQ(a(1.0), 3); + BOOST_TEST_EQ(a(10.), 4); + BOOST_TEST_EQ(a(-std::numeric_limits::infinity()), -1); + BOOST_TEST_EQ(a(std::numeric_limits::infinity()), 4); + BOOST_TEST_EQ(a(std::numeric_limits::quiet_NaN()), 4); + } + + // regular axis with inverted range + { + axis::regular<> a{2, 1, -2}; + BOOST_TEST_EQ(a[-1].lower(), std::numeric_limits::infinity()); + BOOST_TEST_EQ(a[0].lower(), 1); + BOOST_TEST_EQ(a[1].lower(), -0.5); + BOOST_TEST_EQ(a[2].lower(), -2); + BOOST_TEST_EQ(a[2].upper(), -std::numeric_limits::infinity()); + BOOST_TEST_EQ(a(2), -1); + BOOST_TEST_EQ(a(1.001), -1); + BOOST_TEST_EQ(a(1), 0); + BOOST_TEST_EQ(a(0), 0); + BOOST_TEST_EQ(a(-0.499), 0); + BOOST_TEST_EQ(a(-0.5), 1); + BOOST_TEST_EQ(a(-1), 1); + BOOST_TEST_EQ(a(-2), 2); + BOOST_TEST_EQ(a(-20), 2); + } + + // axis::regular with log transform + { + axis::regular> b{2, 1e0, 1e2}; + BOOST_TEST_EQ(b[-1].lower(), 0.0); + BOOST_TEST_IS_CLOSE(b[0].lower(), 1.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[1].lower(), 10.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[2].lower(), 100.0, 1e-9); + BOOST_TEST_EQ(b[2].upper(), std::numeric_limits::infinity()); + + BOOST_TEST_EQ(b(-1), 2); // produces NaN in conversion + BOOST_TEST_EQ(b(0), -1); + BOOST_TEST_EQ(b(1), 0); + BOOST_TEST_EQ(b(9), 0); + BOOST_TEST_EQ(b(10), 1); + BOOST_TEST_EQ(b(90), 1); + BOOST_TEST_EQ(b(100), 2); + BOOST_TEST_EQ(b(std::numeric_limits::infinity()), 2); + } + + // axis::regular with sqrt transform + { + axis::regular> b{2, 0, 4}; + // this is weird: -inf * -inf = inf, thus the lower bound + BOOST_TEST_EQ(b[-1].lower(), std::numeric_limits::infinity()); + BOOST_TEST_IS_CLOSE(b[0].lower(), 0.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[1].lower(), 1.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[2].lower(), 4.0, 1e-9); + BOOST_TEST_EQ(b[2].upper(), std::numeric_limits::infinity()); + + BOOST_TEST_EQ(b(-1), 2); // produces NaN in conversion + BOOST_TEST_EQ(b(0), 0); + BOOST_TEST_EQ(b(0.99), 0); + BOOST_TEST_EQ(b(1), 1); + BOOST_TEST_EQ(b(3.99), 1); + BOOST_TEST_EQ(b(4), 2); + BOOST_TEST_EQ(b(100), 2); + BOOST_TEST_EQ(b(std::numeric_limits::infinity()), 2); + } + + // axis::regular with quantity + { + using namespace boost::units; + using namespace boost::units::si; + using Q = quantity; + + axis::regular> b(2, 0 * meter, 2 * meter); + BOOST_TEST_EQ(b[-1].lower() / meter, -std::numeric_limits::infinity()); + BOOST_TEST_IS_CLOSE(b[0].lower() / meter, 0.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[1].lower() / meter, 1.0, 1e-9); + BOOST_TEST_IS_CLOSE(b[2].lower() / meter, 2.0, 1e-9); + BOOST_TEST_EQ(b[2].upper() / meter, std::numeric_limits::infinity()); + + BOOST_TEST_EQ(b(-1 * meter), -1); // produces NaN in conversion + BOOST_TEST_EQ(b(0 * meter), 0); + BOOST_TEST_EQ(b(0.99 * meter), 0); + BOOST_TEST_EQ(b(1 * meter), 1); + BOOST_TEST_EQ(b(1.99 * meter), 1); + BOOST_TEST_EQ(b(2 * meter), 2); + BOOST_TEST_EQ(b(100 * meter), 2); + BOOST_TEST_EQ(b(std::numeric_limits::infinity() * meter), 2); + } + + // iterators + { + enum { A, B, C }; + test_axis_iterator(axis::regular<>(5, 0, 1, "", axis::option_type::none), 0, 5); + test_axis_iterator( + axis::regular<>(5, 0, 1, "", axis::option_type::underflow_and_overflow), 0, 5); + } + + // bin_type streamable + { + auto test = [](const auto& x, const char* ref) { + std::ostringstream os; + os << x; + BOOST_TEST_EQ(os.str(), std::string(ref)); + }; + + auto a = axis::regular<>(2, 0, 1); + test(a[0], "[0, 0.5)"); + } + + return boost::report_errors(); +} diff --git a/test/axis_test.cpp b/test/axis_test.cpp index 6dc9c1d6..4a31f2ef 100644 --- a/test/axis_test.cpp +++ b/test/axis_test.cpp @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include #include @@ -27,28 +25,10 @@ using namespace boost::histogram; -#define BOOST_TEST_IS_CLOSE(a, b, eps) BOOST_TEST(std::abs(a - b) < eps) - -template -void test_axis_iterator(const Axis& a, int begin, int end) { - for (auto bin : a) { - BOOST_TEST_EQ(bin.idx(), begin); - BOOST_TEST_EQ(bin, a[begin]); - ++begin; - } - BOOST_TEST_EQ(begin, end); - auto rit = a.rbegin(); - for (; rit != a.rend(); ++rit) { - BOOST_TEST_EQ(rit->idx(), --begin); - BOOST_TEST_EQ(*rit, a[begin]); - } -} - int main() { // bad_ctors { auto empty = std::vector(0); - BOOST_TEST_THROWS(axis::regular<>(0, 0, 1), std::invalid_argument); BOOST_TEST_THROWS(axis::circular<>(0), std::invalid_argument); BOOST_TEST_THROWS((axis::variable<>(empty)), std::invalid_argument); BOOST_TEST_THROWS(axis::variable<>({1.0}), std::invalid_argument); @@ -56,117 +36,6 @@ int main() { BOOST_TEST_THROWS((axis::category<>(empty)), std::invalid_argument); } - // axis::regular - { - axis::regular<> a{4, -2, 2}; - BOOST_TEST_EQ(a[-1].lower(), -std::numeric_limits::infinity()); - BOOST_TEST_EQ(a[a.size()].upper(), std::numeric_limits::infinity()); - axis::regular<> b; - BOOST_TEST_NE(a, b); - b = a; - BOOST_TEST_EQ(a, b); - b = b; - BOOST_TEST_EQ(a, b); - axis::regular<> c = std::move(b); - BOOST_TEST_EQ(c, a); - axis::regular<> d; - BOOST_TEST_NE(c, d); - d = std::move(c); - BOOST_TEST_EQ(d, a); - BOOST_TEST_EQ(a(-10.), -1); - BOOST_TEST_EQ(a(-2.1), -1); - BOOST_TEST_EQ(a(-2.0), 0); - BOOST_TEST_EQ(a(-1.1), 0); - BOOST_TEST_EQ(a(0.0), 2); - BOOST_TEST_EQ(a(0.9), 2); - BOOST_TEST_EQ(a(1.0), 3); - BOOST_TEST_EQ(a(10.), 4); - BOOST_TEST_EQ(a(-std::numeric_limits::infinity()), -1); - BOOST_TEST_EQ(a(std::numeric_limits::infinity()), 4); - BOOST_TEST_EQ(a(std::numeric_limits::quiet_NaN()), 4); - } - - // regular axis with inverted range - { - axis::regular<> a{2, 1, -2}; - BOOST_TEST_EQ(a[-1].lower(), std::numeric_limits::infinity()); - BOOST_TEST_EQ(a[0].lower(), 1); - BOOST_TEST_EQ(a[1].lower(), -0.5); - BOOST_TEST_EQ(a[2].lower(), -2); - BOOST_TEST_EQ(a[2].upper(), -std::numeric_limits::infinity()); - BOOST_TEST_EQ(a(2), -1); - BOOST_TEST_EQ(a(1.001), -1); - BOOST_TEST_EQ(a(1), 0); - BOOST_TEST_EQ(a(0), 0); - BOOST_TEST_EQ(a(-0.499), 0); - BOOST_TEST_EQ(a(-0.5), 1); - BOOST_TEST_EQ(a(-1), 1); - BOOST_TEST_EQ(a(-2), 2); - BOOST_TEST_EQ(a(-20), 2); - } - - // axis::regular with log transform - { - axis::regular> b{2, 1e0, 1e2}; - BOOST_TEST_EQ(b[-1].lower(), 0.0); - BOOST_TEST_IS_CLOSE(b[0].lower(), 1.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[1].lower(), 10.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[2].lower(), 100.0, 1e-9); - BOOST_TEST_EQ(b[2].upper(), std::numeric_limits::infinity()); - - BOOST_TEST_EQ(b(-1), 2); // produces NaN in conversion - BOOST_TEST_EQ(b(0), -1); - BOOST_TEST_EQ(b(1), 0); - BOOST_TEST_EQ(b(9), 0); - BOOST_TEST_EQ(b(10), 1); - BOOST_TEST_EQ(b(90), 1); - BOOST_TEST_EQ(b(100), 2); - BOOST_TEST_EQ(b(std::numeric_limits::infinity()), 2); - } - - // axis::regular with sqrt transform - { - axis::regular> b{2, 0, 4}; - // this is weird: -inf * -inf = inf, thus the lower bound - BOOST_TEST_EQ(b[-1].lower(), std::numeric_limits::infinity()); - BOOST_TEST_IS_CLOSE(b[0].lower(), 0.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[1].lower(), 1.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[2].lower(), 4.0, 1e-9); - BOOST_TEST_EQ(b[2].upper(), std::numeric_limits::infinity()); - - BOOST_TEST_EQ(b(-1), 2); // produces NaN in conversion - BOOST_TEST_EQ(b(0), 0); - BOOST_TEST_EQ(b(0.99), 0); - BOOST_TEST_EQ(b(1), 1); - BOOST_TEST_EQ(b(3.99), 1); - BOOST_TEST_EQ(b(4), 2); - BOOST_TEST_EQ(b(100), 2); - BOOST_TEST_EQ(b(std::numeric_limits::infinity()), 2); - } - - // axis::regular with quantity - { - using namespace boost::units; - using namespace boost::units::si; - using Q = quantity; - - axis::regular> b(2, 0 * meter, 2 * meter); - BOOST_TEST_EQ(b[-1].lower() / meter, -std::numeric_limits::infinity()); - BOOST_TEST_IS_CLOSE(b[0].lower() / meter, 0.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[1].lower() / meter, 1.0, 1e-9); - BOOST_TEST_IS_CLOSE(b[2].lower() / meter, 2.0, 1e-9); - BOOST_TEST_EQ(b[2].upper() / meter, std::numeric_limits::infinity()); - - BOOST_TEST_EQ(b(-1 * meter), -1); // produces NaN in conversion - BOOST_TEST_EQ(b(0 * meter), 0); - BOOST_TEST_EQ(b(0.99 * meter), 0); - BOOST_TEST_EQ(b(1 * meter), 1); - BOOST_TEST_EQ(b(1.99 * meter), 1); - BOOST_TEST_EQ(b(2 * meter), 2); - BOOST_TEST_EQ(b(100 * meter), 2); - BOOST_TEST_EQ(b(std::numeric_limits::infinity() * meter), 2); - } - // axis::circular { axis::circular<> a{4, 0, 1}; @@ -284,7 +153,6 @@ int main() { // iterators { enum { A, B, C }; - test_axis_iterator(axis::regular<>(5, 0, 1, "", axis::option_type::none), 0, 5); test_axis_iterator( axis::regular<>(5, 0, 1, "", axis::option_type::underflow_and_overflow), 0, 5); test_axis_iterator(axis::circular<>(5, 0, 1, ""), 0, 5); @@ -389,9 +257,6 @@ int main() { BOOST_TEST_EQ(os.str(), std::string(ref)); }; - auto a = axis::regular<>(2, 0, 1); - test(a[0], "[0, 0.5)"); - auto b = axis::category<>({1, 2}); test(b[0], "1"); } diff --git a/test/utility.hpp b/test/utility.hpp index 6f8555bc..668d9e29 100644 --- a/test/utility.hpp +++ b/test/utility.hpp @@ -7,6 +7,7 @@ #ifndef BOOST_HISTOGRAM_TEST_UTILITY_HPP #define BOOST_HISTOGRAM_TEST_UTILITY_HPP +#include #include #include #include @@ -129,6 +130,23 @@ constexpr bool operator!=(const tracing_allocator& t, return !operator==(t, u); } +template +void test_axis_iterator(const Axis& a, int begin, int end) { + for (auto bin : a) { + BOOST_TEST_EQ(bin.idx(), begin); + BOOST_TEST_EQ(bin, a[begin]); + ++begin; + } + BOOST_TEST_EQ(begin, end); + auto rit = a.rbegin(); + for (; rit != a.rend(); ++rit) { + BOOST_TEST_EQ(rit->idx(), --begin); + BOOST_TEST_EQ(*rit, a[begin]); + } +} + +#define BOOST_TEST_IS_CLOSE(a, b, eps) BOOST_TEST(std::abs(a - b) < eps) + } // namespace histogram } // namespace boost