mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-09 14:57:57 +00:00
add binary axis
This commit is contained in:
parent
1be4c4b3f2
commit
5253358988
@ -38,6 +38,7 @@ matrix:
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 5 --jobs 3" throw_exception
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 5 --jobs 3" smart_ptr
|
||||
- python tools/boostdep/depinst/depinst.py --git_args "--depth 5 --jobs 3" move
|
||||
- git submodule update --init --depth 5 libs/function libs/type_index
|
||||
|
||||
script:
|
||||
mkdir build && cd build &&
|
||||
|
@ -31,6 +31,7 @@ function(add_benchmark NAME)
|
||||
|
||||
endfunction()
|
||||
|
||||
add_benchmark(axis_size)
|
||||
add_benchmark(axis_index)
|
||||
add_benchmark(histogram_filling)
|
||||
add_benchmark(histogram_iteration)
|
||||
|
@ -57,6 +57,12 @@ static void category(benchmark::State& state) {
|
||||
for (auto _ : state) benchmark::DoNotOptimize(a.index(gen()));
|
||||
}
|
||||
|
||||
static void binary(benchmark::State& state) {
|
||||
auto a = axis::binary<>();
|
||||
generator<uniform_int> gen(1);
|
||||
for (auto _ : state) benchmark::DoNotOptimize(a.index(static_cast<bool>(gen())));
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(regular, uniform);
|
||||
BENCHMARK_TEMPLATE(regular, normal);
|
||||
BENCHMARK_TEMPLATE(circular, uniform);
|
||||
@ -68,3 +74,4 @@ BENCHMARK_TEMPLATE(integer, double, normal);
|
||||
BENCHMARK_TEMPLATE(variable, uniform)->RangeMultiplier(10)->Range(10, 10000);
|
||||
BENCHMARK_TEMPLATE(variable, normal)->RangeMultiplier(10)->Range(10, 10000);
|
||||
BENCHMARK(category)->RangeMultiplier(10)->Range(10, 10000);
|
||||
BENCHMARK(binary);
|
||||
|
@ -20,7 +20,9 @@ int main() {
|
||||
using variable = axis::variable<>;
|
||||
using integer = axis::integer<>;
|
||||
using category = axis::category<>;
|
||||
using variant = axis::variant<regular, circular, variable, integer, category>;
|
||||
using binary = axis::binary<>;
|
||||
using binary_no_metadata = axis::binary<axis::null_type>;
|
||||
using variant = axis::variant<regular, circular, variable, integer, category, binary>;
|
||||
|
||||
SHOW_SIZE(regular);
|
||||
SHOW_SIZE(regular_float);
|
||||
@ -30,5 +32,7 @@ int main() {
|
||||
SHOW_SIZE(variable);
|
||||
SHOW_SIZE(integer);
|
||||
SHOW_SIZE(category);
|
||||
SHOW_SIZE(binary);
|
||||
SHOW_SIZE(binary_no_metadata);
|
||||
SHOW_SIZE(variant);
|
||||
}
|
@ -57,10 +57,14 @@ alias threading :
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
alias libserial : /boost/serialization//boost_serialization : <link>static ;
|
||||
alias libserial :
|
||||
/boost/serialization//boost_serialization :
|
||||
<link>static <warnings>off <rtti>on
|
||||
;
|
||||
|
||||
alias serial :
|
||||
[ run guide_histogram_serialization.cpp libserial ]
|
||||
[ run guide_histogram_serialization.cpp libserial ] :
|
||||
<warnings>off
|
||||
;
|
||||
|
||||
alias all : cxx14 threading serial ;
|
||||
|
@ -35,15 +35,16 @@ std::basic_ostream<CharT, Traits>& handle_nonzero_width(
|
||||
std::basic_ostream<CharT, Traits>& os, const T& x) {
|
||||
const auto w = os.width();
|
||||
os.width(0);
|
||||
counting_streambuf<CharT, Traits> cb;
|
||||
const auto saved = os.rdbuf(&cb);
|
||||
os << x;
|
||||
os.rdbuf(saved);
|
||||
std::streamsize count = 0;
|
||||
{
|
||||
auto g = make_count_guard(os, count);
|
||||
os << x;
|
||||
}
|
||||
if (os.flags() & std::ios::left) {
|
||||
os << x;
|
||||
for (auto i = cb.count; i < w; ++i) os << os.fill();
|
||||
for (auto i = count; i < w; ++i) os << os.fill();
|
||||
} else {
|
||||
for (auto i = cb.count; i < w; ++i) os << os.fill();
|
||||
for (auto i = count; i < w; ++i) os << os.fill();
|
||||
os << x;
|
||||
}
|
||||
return os;
|
||||
|
@ -17,6 +17,7 @@
|
||||
[1]: histogram/reference.html#header.boost.histogram.axis.ostream_hpp
|
||||
*/
|
||||
|
||||
#include <boost/histogram/axis/binary.hpp>
|
||||
#include <boost/histogram/axis/category.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
|
74
include/boost/histogram/axis/binary.hpp
Normal file
74
include/boost/histogram/axis/binary.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright Hans Dembinski 2020
|
||||
//
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_BINARY_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_BINARY_HPP
|
||||
|
||||
#include <boost/core/nvp.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/metadata_base.hpp>
|
||||
#include <boost/histogram/detail/relaxed_equal.hpp>
|
||||
#include <boost/histogram/detail/replace_type.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <class MetaData>
|
||||
class binary : public iterator_mixin<binary<MetaData>>, public metadata_base_t<MetaData> {
|
||||
using value_type = bool;
|
||||
using metadata_base = metadata_base_t<MetaData>;
|
||||
using metadata_type = typename metadata_base::metadata_type;
|
||||
|
||||
public:
|
||||
explicit binary(metadata_type meta = {}) : metadata_base(std::move(meta)) {}
|
||||
|
||||
index_type index(value_type x) const noexcept { return static_cast<index_type>(x); }
|
||||
|
||||
value_type value(index_type i) const noexcept { return static_cast<value_type>(i); }
|
||||
|
||||
value_type bin(index_type i) const noexcept { return value(i); }
|
||||
|
||||
index_type size() const noexcept { return 2; }
|
||||
|
||||
static constexpr bool inclusive() noexcept { return true; }
|
||||
|
||||
template <class M>
|
||||
bool operator==(const binary<M>& o) const noexcept {
|
||||
return detail::relaxed_equal{}(this->metadata(), o.metadata());
|
||||
}
|
||||
|
||||
template <class M>
|
||||
bool operator!=(const binary<M>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned /* version */) {
|
||||
ar& make_nvp("meta", this->metadata());
|
||||
}
|
||||
|
||||
private:
|
||||
template <class M>
|
||||
friend class binary;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
binary()->binary<null_type>;
|
||||
|
||||
template <class M>
|
||||
binary(M)->binary<detail::replace_type<std::decay_t<M>, const char*, std::string>>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_HISTOGRAM_AXIS_BINARY_HPP
|
@ -96,25 +96,9 @@ public:
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
return detail::static_if<std::is_floating_point<value_type>>(
|
||||
[this](const auto z) -> index_type {
|
||||
// need to handle NaN, cannot simply cast to int and call int-implementation
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z))
|
||||
return static_cast<index_type>(std::floor(z) -
|
||||
std::floor(z / this->size()) * this->size());
|
||||
} else if (z < this->size())
|
||||
return z >= 0 ? static_cast<index_type>(z) : -1;
|
||||
return this->size();
|
||||
},
|
||||
[this](const auto z) -> index_type {
|
||||
if (options_type::test(option::circular))
|
||||
return static_cast<index_type>(z - std::floor(float(z) / this->size()) *
|
||||
this->size());
|
||||
if (z < this->size()) return z >= 0 ? z : -1;
|
||||
return this->size();
|
||||
},
|
||||
x - min_);
|
||||
return index_impl(options_type::test(axis::option::circular),
|
||||
std::is_floating_point<value_type>{},
|
||||
static_cast<double>(x - min_));
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
@ -193,6 +177,24 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// axis not circular
|
||||
template <class B>
|
||||
index_type index_impl(std::false_type, B, double z) const noexcept {
|
||||
if (z < size()) return z >= 0 ? static_cast<index_type>(z) : -1;
|
||||
return size();
|
||||
}
|
||||
|
||||
// value_type is integer, axis circular
|
||||
index_type index_impl(std::true_type, std::false_type, double z) const noexcept {
|
||||
return static_cast<index_type>(z - std::floor(z / size()) * size());
|
||||
}
|
||||
|
||||
// value_type is floating point, must handle +/-infinite or nan, axis circular
|
||||
index_type index_impl(std::true_type, std::true_type, double z) const noexcept {
|
||||
if (std::isfinite(z)) return index_impl(std::true_type{}, std::false_type{}, z);
|
||||
return z < size() ? -1 : size();
|
||||
}
|
||||
|
||||
index_type size_{0};
|
||||
value_type min_{0};
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/detail/detect.hpp>
|
||||
#include <boost/histogram/detail/static_if.hpp>
|
||||
#include <boost/histogram/detail/counting_streambuf.hpp>
|
||||
#include <boost/histogram/detail/priority.hpp>
|
||||
#include <boost/histogram/detail/type_name.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
@ -40,26 +40,49 @@ namespace boost {
|
||||
namespace histogram {
|
||||
|
||||
namespace detail {
|
||||
inline const char* axis_suffix(const axis::transform::id&) { return ""; }
|
||||
inline const char* axis_suffix(const axis::transform::log&) { return "_log"; }
|
||||
inline const char* axis_suffix(const axis::transform::sqrt&) { return "_sqrt"; }
|
||||
inline const char* axis_suffix(const axis::transform::pow&) { return "_pow"; }
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_metadata(OStream& os, const T& t) {
|
||||
detail::static_if<detail::is_streamable<T>>(
|
||||
[&os](const auto& t) {
|
||||
std::ostringstream oss;
|
||||
oss << t;
|
||||
if (!oss.str().empty()) { os << ", metadata=" << std::quoted(oss.str()); }
|
||||
},
|
||||
[&os](const auto&) { os << ", metadata=" << detail::type_name<T>(); }, t);
|
||||
auto ostream_any_impl(OStream& os, const T& t, priority<1>) -> decltype(os << t) {
|
||||
return os << t;
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
OStream& ostream_any_impl(OStream& os, const T&, priority<0>) {
|
||||
return os << type_name<T>();
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
OStream& ostream_any(OStream& os, const T& t) {
|
||||
return ostream_any_impl(os, t, priority<1>{});
|
||||
}
|
||||
|
||||
template <class OStream, class... Ts>
|
||||
OStream& ostream_any_quoted(OStream& os, const std::basic_string<Ts...>& s) {
|
||||
return os << std::quoted(s);
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
OStream& ostream_any_quoted(OStream& os, const T& t) {
|
||||
return ostream_any(os, t);
|
||||
}
|
||||
|
||||
template <class... Ts, class T>
|
||||
std::basic_ostream<Ts...>& ostream_metadata(std::basic_ostream<Ts...>& os, const T& t,
|
||||
const char* prefix = ", ") {
|
||||
std::streamsize count = 0;
|
||||
{
|
||||
auto g = make_count_guard(os, count);
|
||||
ostream_any(os, t);
|
||||
}
|
||||
if (!count) return os;
|
||||
os << prefix << "metadata=";
|
||||
return ostream_any_quoted(os, t);
|
||||
}
|
||||
|
||||
template <class OStream>
|
||||
void stream_options(OStream& os, const unsigned bits) {
|
||||
os << ", options=";
|
||||
void ostream_options(OStream& os, const unsigned bits) {
|
||||
bool first = true;
|
||||
os << ", options=";
|
||||
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(x) \
|
||||
if (bits & axis::option::x) { \
|
||||
@ -81,24 +104,6 @@ void stream_options(OStream& os, const unsigned bits) {
|
||||
if (first) os << "none";
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_transform(OStream&, const T&) {}
|
||||
|
||||
template <class OStream>
|
||||
void stream_transform(OStream& os, const axis::transform::pow& t) {
|
||||
os << ", power=" << t.power;
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void stream_value(OStream& os, const T& t) {
|
||||
os << t;
|
||||
}
|
||||
|
||||
template <class OStream, class... Ts>
|
||||
void stream_value(OStream& os, const std::basic_string<Ts...>& t) {
|
||||
os << std::quoted(t);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace axis {
|
||||
@ -114,40 +119,58 @@ std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const null_
|
||||
template <class... Ts, class U>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const interval_view<U>& i) {
|
||||
os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
return os;
|
||||
return os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class U>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const polymorphic_bin<U>& i) {
|
||||
if (i.is_discrete())
|
||||
os << static_cast<double>(i);
|
||||
else
|
||||
os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
if (i.is_discrete()) return os << static_cast<double>(i);
|
||||
return os << "[" << i.lower() << ", " << i.upper() << ")";
|
||||
}
|
||||
|
||||
namespace transform {
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const id&) {
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const log&) {
|
||||
return os << "transform::log{}";
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const sqrt&) {
|
||||
return os << "transform::sqrt{}";
|
||||
}
|
||||
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const pow& p) {
|
||||
return os << "transform::pow{" << p.power << "}";
|
||||
}
|
||||
} // namespace transform
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const regular<Us...>& a) {
|
||||
os << "regular" << detail::axis_suffix(a.transform()) << "(" << a.size() << ", "
|
||||
<< a.value(0) << ", " << a.value(a.size());
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
detail::stream_transform(os, a.transform());
|
||||
os << ")";
|
||||
return os;
|
||||
os << "regular(";
|
||||
const auto pos = os.tellp();
|
||||
os << a.transform();
|
||||
if (os.tellp() > pos) os << ", ";
|
||||
os << a.size() << ", " << a.value(0) << ", " << a.value(a.size());
|
||||
detail::ostream_metadata(os, a.metadata());
|
||||
detail::ostream_options(os, a.options());
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const integer<Us...>& a) {
|
||||
os << "integer(" << a.value(0) << ", " << a.value(a.size());
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
detail::ostream_metadata(os, a.metadata());
|
||||
detail::ostream_options(os, a.options());
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
@ -155,10 +178,9 @@ std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const variable<Us...>& a) {
|
||||
os << "variable(" << a.value(0);
|
||||
for (index_type i = 1, n = a.size(); i <= n; ++i) { os << ", " << a.value(i); }
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
detail::ostream_metadata(os, a.metadata());
|
||||
detail::ostream_options(os, a.options());
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
@ -166,26 +188,25 @@ std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const category<Us...>& a) {
|
||||
os << "category(";
|
||||
for (index_type i = 0, n = a.size(); i < n; ++i) {
|
||||
detail::stream_value(os, a.value(i));
|
||||
detail::ostream_any_quoted(os, a.value(i));
|
||||
os << (i == (a.size() - 1) ? "" : ", ");
|
||||
}
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
return os;
|
||||
detail::ostream_metadata(os, a.metadata());
|
||||
detail::ostream_options(os, a.options());
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class M>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const binary<M>& a) {
|
||||
os << "binary(";
|
||||
detail::ostream_metadata(os, a.metadata(), "");
|
||||
return os << ")";
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os,
|
||||
const variant<Us...>& v) {
|
||||
visit(
|
||||
[&os](const auto& x) {
|
||||
using A = std::decay_t<decltype(x)>;
|
||||
detail::static_if<detail::is_streamable<A>>(
|
||||
[&os](const auto& x) { os << x; },
|
||||
[&os](const auto&) { os << "<unstreamable>"; }, x);
|
||||
},
|
||||
v);
|
||||
visit([&os](const auto& x) { detail::ostream_any(os, x); }, v);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef BOOST_HISTOGRAM_DETAIL_COUNTING_STREAMBUF_HPP
|
||||
#define BOOST_HISTOGRAM_DETAIL_COUNTING_STREAMBUF_HPP
|
||||
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <ostream>
|
||||
#include <streambuf>
|
||||
|
||||
namespace boost {
|
||||
@ -20,19 +22,54 @@ struct counting_streambuf : std::basic_streambuf<CharT, Traits> {
|
||||
using typename base_t::char_type;
|
||||
using typename base_t::int_type;
|
||||
|
||||
std::streamsize count = 0;
|
||||
std::streamsize* p_count;
|
||||
|
||||
counting_streambuf(std::streamsize& c) : p_count(&c) {}
|
||||
|
||||
std::streamsize xsputn(const char_type* /* s */, std::streamsize n) override {
|
||||
count += n;
|
||||
*p_count += n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int_type overflow(int_type ch) override {
|
||||
++count;
|
||||
++*p_count;
|
||||
return ch;
|
||||
}
|
||||
};
|
||||
|
||||
template <class C, class T>
|
||||
struct count_guard {
|
||||
using bos = std::basic_ostream<C, T>;
|
||||
using bsb = std::basic_streambuf<C, T>;
|
||||
|
||||
counting_streambuf<C, T> csb;
|
||||
bos* p_os;
|
||||
bsb* p_rdbuf;
|
||||
|
||||
count_guard(bos& os, std::streamsize& s) : csb(s), p_os(&os), p_rdbuf(os.rdbuf(&csb)) {}
|
||||
|
||||
count_guard(count_guard&& o)
|
||||
: csb(o.csb), p_os(boost::exchange(o.p_os, nullptr)), p_rdbuf(o.p_rdbuf) {}
|
||||
|
||||
count_guard& operator=(count_guard&& o) {
|
||||
if (this != &o) {
|
||||
csb = std::move(o.csb);
|
||||
p_os = boost::exchange(o.p_os, nullptr);
|
||||
p_rdbuf = o.p_rdbuf;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
~count_guard() {
|
||||
if (p_os) p_os->rdbuf(p_rdbuf);
|
||||
}
|
||||
};
|
||||
|
||||
template <class C, class T>
|
||||
count_guard<C, T> make_count_guard(std::basic_ostream<C, T>& os, std::streamsize& s) {
|
||||
return {os, s};
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
@ -325,9 +325,9 @@ auto fill(std::true_type, ArgTraits, const std::size_t offset, S& storage, A& ax
|
||||
growing{}, offset, storage, axes,
|
||||
pack_args<ArgTraits::start::value, ArgTraits::nargs::value>(
|
||||
typename ArgTraits::wpos{}, typename ArgTraits::spos{}, args));
|
||||
return (BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank")),
|
||||
storage.end());
|
||||
return BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank")),
|
||||
storage.end();
|
||||
}
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 0)
|
||||
|
@ -21,7 +21,7 @@ std::string type_name_impl(boost::type<T>) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string type_name_impl(boost::type<const T>) {
|
||||
std::string type_name_impl(boost::type<T const>) {
|
||||
return type_name_impl(boost::type<T>{}) + " const";
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,9 @@ template <class Value = int, class MetaData = use_default, class Options = use_d
|
||||
class Allocator = std::allocator<Value>>
|
||||
class category;
|
||||
|
||||
template <class MetaData = use_default>
|
||||
class binary;
|
||||
|
||||
template <class... Ts>
|
||||
class variant;
|
||||
|
||||
@ -163,11 +166,11 @@ namespace detail {
|
||||
|
||||
template <class T>
|
||||
struct buffer_size_impl
|
||||
: std::integral_constant<unsigned, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT> {};
|
||||
: std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT> {};
|
||||
|
||||
template <class... Ts>
|
||||
struct buffer_size_impl<std::tuple<Ts...>>
|
||||
: std::integral_constant<unsigned, sizeof...(Ts)> {};
|
||||
: std::integral_constant<std::size_t, sizeof...(Ts)> {};
|
||||
|
||||
template <class T>
|
||||
using buffer_size = typename buffer_size_impl<T>::type;
|
||||
|
@ -163,7 +163,7 @@ public:
|
||||
unsigned d = 0;
|
||||
iter_.indices_.hist_->for_each_axis([&](const auto& a) {
|
||||
const auto w = axis::traits::width_as<double>(a, this->index(d++));
|
||||
x *= w ? w : 1;
|
||||
x *= w != 0 ? w : 1;
|
||||
});
|
||||
return get() / x;
|
||||
}
|
||||
|
@ -8,11 +8,11 @@
|
||||
#ifndef BOOST_HISTOGRAM_OSTREAM_HPP
|
||||
#define BOOST_HISTOGRAM_OSTREAM_HPP
|
||||
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/histogram/accumulators/ostream.hpp>
|
||||
#include <boost/histogram/axis/ostream.hpp>
|
||||
#include <boost/histogram/detail/counting_streambuf.hpp>
|
||||
#include <boost/histogram/detail/detect.hpp> // is_streamable
|
||||
#include <boost/histogram/detail/static_if.hpp>
|
||||
#include <boost/histogram/detail/priority.hpp>
|
||||
#include <boost/histogram/indexed.hpp>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
@ -48,15 +48,15 @@ public:
|
||||
template <class T>
|
||||
tabular_ostream_wrapper& operator<<(const T& t) {
|
||||
if (collect_) {
|
||||
if (static_cast<std::size_t>(iter_ - base_t::begin()) == size_) {
|
||||
if (static_cast<unsigned>(iter_ - base_t::begin()) == size_) {
|
||||
++size_;
|
||||
BOOST_ASSERT(size_ <= N);
|
||||
BOOST_ASSERT(iter_ != end());
|
||||
*iter_ = 0;
|
||||
}
|
||||
cbuf_.count = 0;
|
||||
count_ = 0;
|
||||
os_ << t;
|
||||
*iter_ = std::max(*iter_, static_cast<int>(cbuf_.count));
|
||||
*iter_ = std::max(*iter_, static_cast<int>(count_));
|
||||
} else {
|
||||
BOOST_ASSERT(iter_ != end());
|
||||
os_ << std::setw(*iter_) << t;
|
||||
@ -80,7 +80,8 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit tabular_ostream_wrapper(OStream& os) : os_(os), orig_(os_.rdbuf(&cbuf_)) {}
|
||||
explicit tabular_ostream_wrapper(OStream& os)
|
||||
: os_(os), cbuf_(count_), orig_(os_.rdbuf(&cbuf_)) {}
|
||||
|
||||
auto end() { return base_t::begin() + size_; }
|
||||
auto end() const { return base_t::begin() + size_; }
|
||||
@ -94,7 +95,8 @@ public:
|
||||
|
||||
private:
|
||||
typename base_t::iterator iter_ = base_t::begin();
|
||||
std::size_t size_ = 0;
|
||||
unsigned size_ = 0;
|
||||
std::streamsize count_ = 0;
|
||||
bool collect_ = true;
|
||||
OStream& os_;
|
||||
counting_streambuf<char_type, traits_type> cbuf_;
|
||||
@ -102,48 +104,52 @@ private:
|
||||
};
|
||||
|
||||
template <class OStream, class T>
|
||||
void ostream_value(OStream& os, const T& val) {
|
||||
// a value from bin or histogram cell
|
||||
os << std::left;
|
||||
static_if_c<(std::is_convertible<T, double>::value && !std::is_integral<T>::value)>(
|
||||
[](auto& os, const auto& val) {
|
||||
const auto d = static_cast<double>(val);
|
||||
if (std::isfinite(d)) {
|
||||
const auto i = static_cast<std::int64_t>(d);
|
||||
if (i == d) {
|
||||
os << i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
os << std::defaultfloat << std::setprecision(4) << d;
|
||||
},
|
||||
[](auto& os, const auto& val) { os << val; }, os, val);
|
||||
void ostream_value_impl(OStream& os, const T& t,
|
||||
decltype(static_cast<double>(t), priority<1>{})) {
|
||||
// a value from histogram cell
|
||||
const auto d = static_cast<double>(t);
|
||||
if (std::numeric_limits<int>::min() <= d && d <= std::numeric_limits<int>::max()) {
|
||||
const auto i = static_cast<int>(d);
|
||||
if (i == d) {
|
||||
os << i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
os << std::defaultfloat << std::setprecision(4) << d;
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void ostream_value_impl(OStream& os, const T& t, priority<0>) {
|
||||
os << t;
|
||||
}
|
||||
|
||||
template <class OStream, class T>
|
||||
void ostream_value(OStream& os, const T& t) {
|
||||
ostream_value_impl(os << std::left, t, priority<1>{});
|
||||
}
|
||||
|
||||
template <class OStream, class Axis>
|
||||
void ostream_bin(OStream& os, const Axis& ax, const int i) {
|
||||
auto ostream_bin(OStream& os, const Axis& ax, axis::index_type i, std::true_type,
|
||||
priority<1>) -> decltype((void)ax.value(i)) {
|
||||
auto a = ax.value(i), b = ax.value(i + 1);
|
||||
os << std::right << std::defaultfloat << std::setprecision(4);
|
||||
// round edges to zero if deviation from zero is small
|
||||
const auto eps = 1e-8 * std::abs(b - a);
|
||||
if (std::abs(a) < 1e-14 && std::abs(a) < eps) a = 0;
|
||||
if (std::abs(b) < 1e-14 && std::abs(b) < eps) b = 0;
|
||||
os << "[" << a << ", " << b << ")";
|
||||
}
|
||||
|
||||
template <class OStream, class Axis>
|
||||
auto ostream_bin(OStream& os, const Axis& ax, axis::index_type i, std::false_type,
|
||||
priority<1>) -> decltype((void)ax.value(i)) {
|
||||
os << std::right;
|
||||
static_if<has_method_value<Axis>>(
|
||||
[&](const auto& ax) {
|
||||
static_if<axis::traits::is_continuous<Axis>>(
|
||||
[&](const auto& ax) {
|
||||
os << std::defaultfloat << std::setprecision(4);
|
||||
auto a = ax.value(i);
|
||||
auto b = ax.value(i + 1);
|
||||
// round bin edge to zero if deviation from zero is absolut and relatively
|
||||
// small
|
||||
const auto eps = 1e-8 * std::abs(b - a);
|
||||
if (std::abs(a) < 1e-14 && std::abs(a) < eps) a = 0;
|
||||
if (std::abs(b) < 1e-14 && std::abs(b) < eps) b = 0;
|
||||
os << "[" << a << ", " << b << ")";
|
||||
},
|
||||
[&](const auto& ax) { os << ax.value(i); }, ax);
|
||||
},
|
||||
[&](const auto&) { os << i; }, ax);
|
||||
os << ax.value(i);
|
||||
}
|
||||
|
||||
template <class OStream, class... Ts>
|
||||
void ostream_bin(OStream& os, const axis::category<Ts...>& ax, const int i) {
|
||||
void ostream_bin(OStream& os, const axis::category<Ts...>& ax, axis::index_type i,
|
||||
std::false_type, priority<1>) {
|
||||
os << std::right;
|
||||
if (i < ax.size())
|
||||
os << ax.value(i);
|
||||
@ -151,6 +157,12 @@ void ostream_bin(OStream& os, const axis::category<Ts...>& ax, const int i) {
|
||||
os << "other";
|
||||
}
|
||||
|
||||
template <class OStream, class Axis, class B>
|
||||
void ostream_bin(OStream& os, const Axis&, axis::index_type i, B, priority<0>) {
|
||||
os << std::right;
|
||||
os << i;
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
struct line_t {
|
||||
CharT ch;
|
||||
@ -168,19 +180,24 @@ std::basic_ostream<C, T>& operator<<(std::basic_ostream<C, T>& os, line_t<C>&& l
|
||||
return os;
|
||||
}
|
||||
|
||||
template <class OStream, class Axis, class T>
|
||||
void stream_head(OStream& os, const Axis& ax, int index, const T& val) {
|
||||
template <class OStream, class Axis>
|
||||
void ostream_head(OStream& os, const Axis& ax, int index, double val) {
|
||||
axis::visit(
|
||||
[&](const auto& ax) {
|
||||
ostream_bin(os, ax, index);
|
||||
using A = std::decay_t<decltype(ax)>;
|
||||
ostream_bin(os, ax, index, axis::traits::is_continuous<A>{}, priority<1>{});
|
||||
os << ' ';
|
||||
ostream_value(os, val);
|
||||
},
|
||||
ax);
|
||||
}
|
||||
|
||||
// cannot display generalized histograms yet
|
||||
template <class OStream, class Histogram>
|
||||
void ascii_plot(OStream& os, const Histogram& h, int w_total) {
|
||||
void ascii_plot(OStream&, const Histogram&, int, std::false_type) {}
|
||||
|
||||
template <class OStream, class Histogram>
|
||||
void ascii_plot(OStream& os, const Histogram& h, int w_total, std::true_type) {
|
||||
if (w_total == 0) w_total = 78; // TODO detect actual width of terminal
|
||||
|
||||
const auto& ax = h.axis();
|
||||
@ -191,7 +208,7 @@ void ascii_plot(OStream& os, const Histogram& h, int w_total) {
|
||||
tabular_ostream_wrapper<OStream, 7> tos(os);
|
||||
// first pass to get widths
|
||||
for (auto&& v : indexed(h, coverage::all)) {
|
||||
stream_head(tos.row(), ax, v.index(), *v);
|
||||
ostream_head(tos.row(), ax, v.index(), *v);
|
||||
vmin = std::min(vmin, static_cast<double>(*v));
|
||||
vmax = std::max(vmax, static_cast<double>(*v));
|
||||
}
|
||||
@ -201,8 +218,8 @@ void ascii_plot(OStream& os, const Histogram& h, int w_total) {
|
||||
// calculate width useable by bar (notice extra space at top)
|
||||
// <-- head --> |<--- bar ---> |
|
||||
// w_head + 2 + 2
|
||||
const int w_head = std::accumulate(tos.begin(), tos.end(), 0);
|
||||
const int w_bar = w_total - 4 - w_head;
|
||||
const auto w_head = std::accumulate(tos.begin(), tos.end(), 0);
|
||||
const auto w_bar = w_total - 4 - w_head;
|
||||
if (w_bar < 0) return;
|
||||
|
||||
// draw upper line
|
||||
@ -210,7 +227,7 @@ void ascii_plot(OStream& os, const Histogram& h, int w_total) {
|
||||
|
||||
const int zero_offset = static_cast<int>(std::lround((-vmin) / (vmax - vmin) * w_bar));
|
||||
for (auto&& v : indexed(h, coverage::all)) {
|
||||
stream_head(tos.row(), ax, v.index(), *v);
|
||||
ostream_head(tos.row(), ax, v.index(), *v);
|
||||
// rest uses os, not tos
|
||||
os << " |";
|
||||
const int k = static_cast<int>(std::lround(*v / (vmax - vmin) * w_bar));
|
||||
@ -233,10 +250,8 @@ void ostream(OStream& os, const Histogram& h, const bool show_values = true) {
|
||||
unsigned iaxis = 0;
|
||||
const auto rank = h.rank();
|
||||
h.for_each_axis([&](const auto& ax) {
|
||||
using A = std::decay_t<decltype(ax)>;
|
||||
if ((show_values && rank > 0) || rank > 1) os << "\n ";
|
||||
static_if<is_streamable<A>>([&](const auto& ax) { os << ax; },
|
||||
[&](const auto&) { os << "<unstreamable>"; }, ax);
|
||||
ostream_any(os, ax);
|
||||
});
|
||||
|
||||
if (show_values && rank > 0) {
|
||||
@ -285,15 +300,19 @@ std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>&
|
||||
os.width(0);
|
||||
|
||||
using value_type = typename histogram<A, S>::value_type;
|
||||
detail::static_if<std::is_convertible<value_type, double>>(
|
||||
[&os, w](const auto& h) {
|
||||
if (h.rank() == 1) {
|
||||
detail::ostream(os, h, false);
|
||||
detail::ascii_plot(os, h, w);
|
||||
} else
|
||||
detail::ostream(os, h);
|
||||
},
|
||||
[&os](const auto& h) { detail::ostream(os, h); }, h);
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 0)
|
||||
#pragma warning(disable : 4127) // warning to use `if constexpr`
|
||||
#endif
|
||||
if (std::is_convertible<value_type, double>::value && h.rank() == 1) {
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 0)
|
||||
#pragma warning(default : 4127)
|
||||
#endif
|
||||
detail::ostream(os, h, false);
|
||||
detail::ascii_plot(os, h, w, std::is_convertible<value_type, double>{});
|
||||
} else {
|
||||
detail::ostream(os, h);
|
||||
}
|
||||
|
||||
// restore fmt
|
||||
os.flags(flags);
|
||||
|
@ -8,13 +8,8 @@
|
||||
#ifndef BOOST_HISTOGRAM_UNLIMTED_STORAGE_HPP
|
||||
#define BOOST_HISTOGRAM_UNLIMTED_STORAGE_HPP
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 0)
|
||||
#pragma warning(disable : 4996) // temporary fix (deprecation) until fixed in Boost Core
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/alloc_construct.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
@ -643,8 +638,4 @@ private:
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 0)
|
||||
#pragma warning(default: 4996)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -51,11 +51,11 @@ boost_test(TYPE run SOURCES algorithm_project_test.cpp)
|
||||
boost_test(TYPE run SOURCES algorithm_reduce_test.cpp)
|
||||
boost_test(TYPE run SOURCES algorithm_sum_test.cpp)
|
||||
boost_test(TYPE run SOURCES algorithm_empty_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_binary_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_category_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_integer_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_option_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_regular_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_size.cpp)
|
||||
boost_test(TYPE run SOURCES axis_traits_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_variable_test.cpp)
|
||||
boost_test(TYPE run SOURCES axis_variant_test.cpp)
|
||||
|
@ -35,6 +35,7 @@ testing.make-test run-pyd : check_build_system.py :
|
||||
testing.make-test run-pyd : check_odr_test.py : <dependency>odr_test.cpp ;
|
||||
alias odr :
|
||||
[ link odr_main_test.cpp odr_test.cpp ]
|
||||
: <warnings>off
|
||||
;
|
||||
|
||||
alias cxx14 :
|
||||
@ -51,11 +52,11 @@ alias cxx14 :
|
||||
[ run algorithm_reduce_test.cpp ]
|
||||
[ run algorithm_sum_test.cpp ]
|
||||
[ run algorithm_empty_test.cpp ]
|
||||
[ run axis_binary_test.cpp ]
|
||||
[ run axis_category_test.cpp ]
|
||||
[ run axis_integer_test.cpp ]
|
||||
[ run axis_option_test.cpp ]
|
||||
[ run axis_regular_test.cpp ]
|
||||
[ run axis_size.cpp ]
|
||||
[ run axis_traits_test.cpp ]
|
||||
[ run axis_variable_test.cpp ]
|
||||
[ run axis_variant_test.cpp ]
|
||||
@ -136,6 +137,7 @@ alias serialization :
|
||||
[ run histogram_serialization_test.cpp libserial : $(THIS_PATH) ]
|
||||
[ run storage_adaptor_serialization_test.cpp libserial : $(THIS_PATH) ]
|
||||
[ run unlimited_storage_serialization_test.cpp libserial : $(THIS_PATH) ]
|
||||
: <warnings>off
|
||||
;
|
||||
|
||||
alias libserial :
|
||||
|
59
test/axis_binary_test.cpp
Normal file
59
test/axis_binary_test.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
// Copyright 2020 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 <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram/axis/binary.hpp>
|
||||
#include <boost/histogram/axis/ostream.hpp>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include "std_ostream.hpp"
|
||||
#include "throw_exception.hpp"
|
||||
#include "utility_axis.hpp"
|
||||
#include "utility_str.hpp"
|
||||
|
||||
int main() {
|
||||
using namespace boost::histogram;
|
||||
|
||||
BOOST_TEST(std::is_nothrow_move_assignable<axis::binary<>>::value);
|
||||
BOOST_TEST(std::is_nothrow_move_constructible<axis::binary<>>::value);
|
||||
|
||||
// axis::integer with double type
|
||||
{
|
||||
axis::binary<> a{"foo"};
|
||||
BOOST_TEST_EQ(a.metadata(), "foo");
|
||||
a.metadata() = "bar";
|
||||
const auto& cref = a;
|
||||
BOOST_TEST_EQ(cref.metadata(), "bar");
|
||||
cref.metadata() = "foo";
|
||||
BOOST_TEST_EQ(cref.metadata(), "foo");
|
||||
|
||||
BOOST_TEST_EQ(a.index(true), 1);
|
||||
BOOST_TEST_EQ(a.index(false), 0);
|
||||
BOOST_TEST_EQ(a.index(1), 1);
|
||||
BOOST_TEST_EQ(a.index(0), 0);
|
||||
|
||||
BOOST_TEST_CSTR_EQ(str(a).c_str(), "binary(metadata=\"foo\")");
|
||||
|
||||
axis::binary<> b;
|
||||
BOOST_TEST_CSTR_EQ(str(b).c_str(), "binary()");
|
||||
|
||||
BOOST_TEST_NE(a, b);
|
||||
b = a;
|
||||
BOOST_TEST_EQ(a, b);
|
||||
axis::binary<> c = std::move(b);
|
||||
BOOST_TEST_EQ(c, a);
|
||||
axis::binary<> d;
|
||||
BOOST_TEST_NE(c, d);
|
||||
d = std::move(c);
|
||||
BOOST_TEST_EQ(d, a);
|
||||
}
|
||||
|
||||
// iterators
|
||||
test_axis_iterator(axis::binary<>(), 0, 2);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
@ -82,8 +82,9 @@ int main() {
|
||||
BOOST_TEST_EQ(a.value(2), C);
|
||||
BOOST_TEST_THROWS(a.value(3), std::out_of_range);
|
||||
|
||||
BOOST_TEST_EQ(str(a),
|
||||
"category(\"A\", \"B\", \"C\", metadata=\"bar\", options=overflow)");
|
||||
BOOST_TEST_CSTR_EQ(
|
||||
str(a).c_str(),
|
||||
"category(\"A\", \"B\", \"C\", metadata=\"bar\", options=overflow)");
|
||||
}
|
||||
|
||||
// category<int, axis::null_type>: copy, move
|
||||
|
@ -127,10 +127,15 @@ int main() {
|
||||
BOOST_TEST_EQ(a.value(2), 1);
|
||||
BOOST_TEST_EQ(a.value(3), 2);
|
||||
BOOST_TEST_EQ(a.index(-2), 1);
|
||||
BOOST_TEST_EQ(a.index(-1.9), 1);
|
||||
BOOST_TEST_EQ(a.index(-1.1), 1);
|
||||
BOOST_TEST_EQ(a.index(-1), 0);
|
||||
BOOST_TEST_EQ(a.index(0), 1);
|
||||
BOOST_TEST_EQ(a.index(1), 0);
|
||||
BOOST_TEST_EQ(a.index(2), 1);
|
||||
BOOST_TEST_EQ(a.index(2.1), 1);
|
||||
BOOST_TEST_EQ(a.index(2.9), 1);
|
||||
|
||||
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::quiet_NaN()), 2);
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,9 @@ int main() {
|
||||
|
||||
BOOST_TEST_THROWS((axis::regular<double, tr::log>{2, -1, 0}), std::invalid_argument);
|
||||
|
||||
BOOST_TEST_EQ(str(a), "regular_log(2, 1, 100, options=underflow | overflow)");
|
||||
BOOST_TEST_CSTR_EQ(
|
||||
str(a).c_str(),
|
||||
"regular(transform::log{}, 2, 1, 100, options=underflow | overflow)");
|
||||
}
|
||||
|
||||
// with sqrt transform
|
||||
@ -139,7 +141,8 @@ int main() {
|
||||
BOOST_TEST_EQ(a.index(100), 2);
|
||||
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::infinity()), 2);
|
||||
|
||||
BOOST_TEST_EQ(str(a), "regular_sqrt(2, 0, 4, options=underflow | overflow)");
|
||||
BOOST_TEST_EQ(str(a),
|
||||
"regular(transform::sqrt{}, 2, 0, 4, options=underflow | overflow)");
|
||||
}
|
||||
|
||||
// with pow transform
|
||||
@ -162,7 +165,7 @@ int main() {
|
||||
BOOST_TEST_EQ(a.index(std::numeric_limits<double>::infinity()), 2);
|
||||
|
||||
BOOST_TEST_EQ(str(a),
|
||||
"regular_pow(2, 0, 4, options=underflow | overflow, power=0.5)");
|
||||
"regular(transform::pow{0.5}, 2, 0, 4, options=underflow | overflow)");
|
||||
}
|
||||
|
||||
// with step
|
||||
|
@ -6,15 +6,13 @@
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/histogram/axis/category.hpp>
|
||||
#include <boost/histogram/axis/integer.hpp>
|
||||
#include <boost/histogram/axis.hpp>
|
||||
#include <boost/histogram/axis/ostream.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/axis/variant.hpp>
|
||||
#include <boost/histogram/detail/type_name.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include "std_ostream.hpp"
|
||||
#include "throw_exception.hpp"
|
||||
#include "utility_allocator.hpp"
|
||||
#include "utility_axis.hpp"
|
||||
@ -72,7 +70,7 @@ int main() {
|
||||
BOOST_TEST_EQ(r1.metadata(), a.metadata());
|
||||
BOOST_TEST_EQ(r1.options(), a.options());
|
||||
// change original through r1
|
||||
axis::get<A>(r1).metadata() = "bar";
|
||||
r1.metadata() = "bar";
|
||||
BOOST_TEST_EQ(a.metadata(), "bar");
|
||||
r1 = &b;
|
||||
BOOST_TEST_EQ(r1, b);
|
||||
@ -84,8 +82,8 @@ int main() {
|
||||
BOOST_TEST_EQ(r2.size(), 3);
|
||||
BOOST_TEST_EQ(r2.value(0), 1);
|
||||
BOOST_TEST_EQ(r2.metadata(), "bar");
|
||||
b.metadata() = "baz";
|
||||
BOOST_TEST_EQ(r2.metadata(), "baz");
|
||||
r2.metadata() = "baz"; // change original through r2
|
||||
BOOST_TEST_EQ(b.metadata(), "baz");
|
||||
}
|
||||
|
||||
// axis::variant copyable
|
||||
@ -128,8 +126,10 @@ int main() {
|
||||
BOOST_TEST_CSTR_EQ(str(axis).c_str(), ref);
|
||||
};
|
||||
|
||||
test(axis::regular<>(2, -1, 1, "regular1"),
|
||||
"regular(2, -1, 1, metadata=\"regular1\", options=underflow | overflow)");
|
||||
test(axis::regular<>{2, -1, 1, "foo"},
|
||||
"regular(2, -1, 1, metadata=\"foo\", options=underflow | overflow)");
|
||||
|
||||
test(axis::binary<>{"bar"}, "binary(metadata=\"bar\")");
|
||||
|
||||
struct user_defined {};
|
||||
const auto ref = "integer(-1, 1, metadata=" + detail::type_name<user_defined>() +
|
||||
@ -154,26 +154,27 @@ int main() {
|
||||
enum { A, B, C };
|
||||
using variant =
|
||||
axis::variant<axis::regular<>, axis::regular<double, axis::transform::pow>,
|
||||
axis::category<>, axis::integer<>>;
|
||||
axis::category<>, axis::integer<>, axis::binary<>>;
|
||||
std::vector<variant> axes;
|
||||
axes.push_back(axis::regular<>{2, -1, 1});
|
||||
axes.push_back(axis::regular<double, tr::pow>(tr::pow(0.5), 2, 1, 4));
|
||||
axes.push_back(axis::category<>({A, B, C}));
|
||||
axes.push_back(axis::regular<double, tr::pow>{tr::pow{0.5}, 2, 1, 4});
|
||||
axes.push_back(axis::category<>{A, B, C});
|
||||
axes.push_back(axis::integer<>{-1, 1});
|
||||
axes.push_back(axis::binary<>{});
|
||||
for (const auto& a : axes) {
|
||||
BOOST_TEST(!(a == variant()));
|
||||
BOOST_TEST_NE(a, variant{});
|
||||
BOOST_TEST_EQ(a, variant(a));
|
||||
}
|
||||
BOOST_TEST_NOT(axes == std::vector<variant>());
|
||||
BOOST_TEST_NE(axes, std::vector<variant>{});
|
||||
BOOST_TEST(axes == std::vector<variant>(axes));
|
||||
}
|
||||
|
||||
// axis::variant with axis that has incompatible bin type
|
||||
{
|
||||
auto a = axis::variant<axis::category<std::string>>(
|
||||
axis::category<std::string>({"A", "B", "C"}));
|
||||
auto a = axis::variant<axis::category<std::string>>{
|
||||
axis::category<std::string>{"A", "B", "C"}};
|
||||
BOOST_TEST_THROWS(a.bin(0), std::runtime_error);
|
||||
auto b = axis::variant<axis::category<int>>(axis::category<int>({2, 1, 3}));
|
||||
auto b = axis::variant<axis::category<int>>{axis::category<int>{2, 1, 3}};
|
||||
BOOST_TEST_EQ(b.bin(0), 2);
|
||||
BOOST_TEST_EQ(b.bin(0).lower(),
|
||||
b.bin(0).upper()); // lower == upper for bin without interval
|
||||
@ -191,7 +192,7 @@ int main() {
|
||||
BOOST_TEST_EQ(axis.index(9), 1);
|
||||
BOOST_TEST_EQ(axis.size(), 2);
|
||||
BOOST_TEST_EQ(axis.metadata(), axis::null_type{});
|
||||
BOOST_TEST_CSTR_EQ(str(axis).c_str(), "<unstreamable>");
|
||||
BOOST_TEST_EQ(str(axis), detail::type_name<minimal_axis>());
|
||||
BOOST_TEST_THROWS(axis.value(0), std::runtime_error);
|
||||
|
||||
axis = axis::category<std::string>({"A", "B"}, "category");
|
||||
|
@ -84,6 +84,12 @@ int main() {
|
||||
BOOST_TEST_TRAIT_SAME(decltype(category({1, 2}, 0)), category<int, int>);
|
||||
}
|
||||
|
||||
{
|
||||
using axis::binary;
|
||||
BOOST_TEST_TRAIT_SAME(decltype(binary{}), binary<null_type>);
|
||||
BOOST_TEST_TRAIT_SAME(decltype(binary{"foo"}), binary<std::string>);
|
||||
}
|
||||
|
||||
{
|
||||
auto h = histogram(axis::regular(3, -1, 1), axis::integer(0, 4));
|
||||
BOOST_TEST_TRAIT_SAME(decltype(h),
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <boost/histogram/literals.hpp>
|
||||
#include <boost/histogram/storage_adaptor.hpp>
|
||||
#include <boost/histogram/unlimited_storage.hpp>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include "std_ostream.hpp"
|
||||
#include "throw_exception.hpp"
|
||||
@ -104,14 +105,25 @@ int main() {
|
||||
|
||||
// counting_streambuf
|
||||
{
|
||||
dtl::counting_streambuf<char> cbuf;
|
||||
std::ostream os(&cbuf);
|
||||
std::streamsize count = 0;
|
||||
dtl::counting_streambuf<char> csb(count);
|
||||
std::ostream os(&csb);
|
||||
os.put('x');
|
||||
BOOST_TEST_EQ(cbuf.count, 1);
|
||||
BOOST_TEST_EQ(count, 1);
|
||||
os << 12;
|
||||
BOOST_TEST_EQ(cbuf.count, 3);
|
||||
BOOST_TEST_EQ(count, 3);
|
||||
os << "123";
|
||||
BOOST_TEST_EQ(cbuf.count, 6);
|
||||
BOOST_TEST_EQ(count, 6);
|
||||
}
|
||||
{
|
||||
std::streamsize count = 0;
|
||||
auto g = dtl::make_count_guard(std::cout, count);
|
||||
std::cout.put('x');
|
||||
BOOST_TEST_EQ(count, 1);
|
||||
std::cout << 12;
|
||||
BOOST_TEST_EQ(count, 3);
|
||||
std::cout << "123";
|
||||
BOOST_TEST_EQ(count, 6);
|
||||
}
|
||||
|
||||
// sub_array and span
|
||||
|
@ -58,7 +58,7 @@ void run_tests() {
|
||||
" +------------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// regular, narrow
|
||||
@ -77,12 +77,12 @@ void run_tests() {
|
||||
" +-----------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h, 40).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h, 40).c_str(), expected);
|
||||
|
||||
// too narrow
|
||||
BOOST_TEST_CSTR_EQ("BEGIN\n"
|
||||
"histogram(regular(3, -0.5, 1, options=none))END",
|
||||
str(h, 10).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h, 10).c_str(),
|
||||
"BEGIN\n"
|
||||
"histogram(regular(3, -0.5, 1, options=none))END");
|
||||
}
|
||||
|
||||
// regular2
|
||||
@ -102,7 +102,7 @@ void run_tests() {
|
||||
" +-------------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// regular with log
|
||||
@ -111,8 +111,8 @@ void run_tests() {
|
||||
|
||||
const auto expected =
|
||||
"BEGIN\n"
|
||||
"histogram(regular_log(6, 0.001, 1000, metadata=\"foo\", options=underflow | "
|
||||
"overflow))\n"
|
||||
"histogram(regular(transform::log{}, 6, 0.001, 1000, metadata=\"foo\", "
|
||||
"options=underflow | overflow))\n"
|
||||
" +-----------------------------------------------------------+\n"
|
||||
"[ 0, 0.001) 0 | |\n"
|
||||
"[0.001, 0.01) 0 | |\n"
|
||||
@ -125,7 +125,7 @@ void run_tests() {
|
||||
" +-----------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// integer
|
||||
@ -144,7 +144,7 @@ void run_tests() {
|
||||
" +---------------------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// catorgy<string>
|
||||
@ -168,7 +168,7 @@ void run_tests() {
|
||||
" +------------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// histogram with axis that has no value method
|
||||
@ -184,14 +184,16 @@ void run_tests() {
|
||||
|
||||
const auto expected =
|
||||
"BEGIN\n"
|
||||
"histogram(<unstreamable>)\n"
|
||||
"histogram(" +
|
||||
detail::type_name<minimal_axis>() +
|
||||
")\n"
|
||||
" +------------------------------------------------------------------------+\n"
|
||||
"0 3 |===================================================== |\n"
|
||||
"1 4 |======================================================================= |\n"
|
||||
" +------------------------------------------------------------------------+\n"
|
||||
"END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected.c_str());
|
||||
}
|
||||
|
||||
// fallback for 2D
|
||||
@ -212,7 +214,7 @@ void run_tests() {
|
||||
" ( 1 1): 0 (-1 2): nan ( 0 2): 0 ( 1 2): 0 \n"
|
||||
")END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
// fallback for profile
|
||||
@ -227,7 +229,7 @@ void run_tests() {
|
||||
" ( 1): mean(0, 0, -0) \n"
|
||||
")END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,7 +244,7 @@ int main() {
|
||||
const auto expected = "BEGIN\n"
|
||||
"histogram()END";
|
||||
|
||||
BOOST_TEST_CSTR_EQ(expected, str(h).c_str());
|
||||
BOOST_TEST_CSTR_EQ(str(h).c_str(), expected);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
|
Loading…
x
Reference in New Issue
Block a user