add boost on mac
This commit is contained in:
184
macx64/include/boost/histogram/axis/category.hpp
Normal file
184
macx64/include/boost/histogram/axis/category.hpp
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright 2015-2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_CATEGORY_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_CATEGORY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Maps at a set of unique values to bin indices.
|
||||
|
||||
The axis maps a set of values to bins, following the order of arguments in the
|
||||
constructor. The optional overflow bin for this axis counts input values that
|
||||
are not part of the set. Binning has O(N) complexity, but with a very small
|
||||
factor. For small N (the typical use case) it beats other kinds of lookup.
|
||||
|
||||
@tparam Value input value type, must be equal-comparable.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option.
|
||||
@tparam Allocator allocator to use for dynamic memory management.
|
||||
|
||||
The options `underflow` and `circular` are not allowed. The options `growth`
|
||||
and `overflow` are mutually exclusive.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options, class Allocator>
|
||||
class category : public iterator_mixin<category<Value, MetaData, Options, Allocator>> {
|
||||
using value_type = Value;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type = detail::replace_default<Options, option::overflow_t>;
|
||||
static_assert(!options_type::test(option::underflow),
|
||||
"category axis cannot have underflow");
|
||||
static_assert(!options_type::test(option::circular),
|
||||
"category axis cannot be circular");
|
||||
static_assert(!options_type::test(option::growth) ||
|
||||
!options_type::test(option::overflow),
|
||||
"growing category axis cannot have overflow");
|
||||
using allocator_type = Allocator;
|
||||
using vector_type = std::vector<value_type, allocator_type>;
|
||||
|
||||
public:
|
||||
explicit category(allocator_type alloc = {}) : vec_meta_(vector_type(alloc)) {}
|
||||
|
||||
/** Construct from iterator range of unique values.
|
||||
*
|
||||
* \param begin begin of category range of unique values.
|
||||
* \param end end of category range of unique values.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
category(It begin, It end, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: vec_meta_(vector_type(begin, end, alloc), std::move(meta)) {
|
||||
if (size() == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
}
|
||||
|
||||
/** Construct axis from iterable sequence of unique values.
|
||||
*
|
||||
* \param iterable sequence of unique values.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class C, class = detail::requires_iterable<C>>
|
||||
category(const C& iterable, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: category(std::begin(iterable), std::end(iterable), std::move(meta),
|
||||
std::move(alloc)) {}
|
||||
|
||||
/** Construct axis from an initializer list of unique values.
|
||||
*
|
||||
* \param list `std::initializer_list` of unique values.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class U>
|
||||
category(std::initializer_list<U> list, metadata_type meta = {},
|
||||
allocator_type alloc = {})
|
||||
: category(list.begin(), list.end(), std::move(meta), std::move(alloc)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin.
|
||||
category(const category& src, index_type begin, index_type end, unsigned merge)
|
||||
: category(src.vec_meta_.first().begin() + begin,
|
||||
src.vec_meta_.first().begin() + end, src.metadata()) {
|
||||
if (merge > 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for category axis"));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(const value_type& x) const noexcept {
|
||||
const auto beg = vec_meta_.first().begin();
|
||||
const auto end = vec_meta_.first().end();
|
||||
return static_cast<index_type>(std::distance(beg, std::find(beg, end, x)));
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(const value_type& x) {
|
||||
const auto i = index(x);
|
||||
if (i < size()) return std::make_pair(i, 0);
|
||||
vec_meta_.first().emplace_back(x);
|
||||
return std::make_pair(i, -1);
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
/// Throws `std::out_of_range` if the index is out of bounds.
|
||||
decltype(auto) value(index_type idx) const {
|
||||
if (idx < 0 || idx >= size())
|
||||
BOOST_THROW_EXCEPTION(std::out_of_range("category index out of range"));
|
||||
return vec_meta_.first()[idx];
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept { return value(idx); }
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept {
|
||||
return static_cast<index_type>(vec_meta_.first().size());
|
||||
}
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return vec_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return vec_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator==(const category<V, M, O, A>& o) const noexcept {
|
||||
const auto& a = vec_meta_.first();
|
||||
const auto& b = o.vec_meta_.first();
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end()) &&
|
||||
detail::relaxed_equal(metadata(), o.metadata());
|
||||
}
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator!=(const category<V, M, O, A>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vector_type, metadata_type> vec_meta_;
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
friend class category;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
category(std::initializer_list<T>)->category<T>;
|
||||
|
||||
category(std::initializer_list<const char*>)->category<std::string>;
|
||||
|
||||
template <class T>
|
||||
category(std::initializer_list<T>, const char*)->category<T>;
|
||||
|
||||
template <class T, class M>
|
||||
category(std::initializer_list<T>, const M&)->category<T, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
194
macx64/include/boost/histogram/axis/integer.hpp
Normal file
194
macx64/include/boost/histogram/axis/integer.hpp
Normal file
@@ -0,0 +1,194 @@
|
||||
// Copyright 2015-2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTEGER_HPP
|
||||
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Axis for an interval of integer values with unit steps.
|
||||
|
||||
Binning is a O(1) operation. This axis bins faster than a regular axis.
|
||||
|
||||
@tparam Value input value type. Must be integer or floating point.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option (all values allowed).
|
||||
*/
|
||||
template <class Value, class MetaData, class Options>
|
||||
class integer : public iterator_mixin<integer<Value, MetaData, Options>> {
|
||||
static_assert(std::is_integral<Value>::value || std::is_floating_point<Value>::value,
|
||||
"integer axis requires type floating point or integral type");
|
||||
|
||||
using value_type = Value;
|
||||
using local_index_type = std::conditional_t<std::is_integral<value_type>::value,
|
||||
index_type, real_index_type>;
|
||||
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
|
||||
static_assert(!options_type::test(option::circular) ||
|
||||
std::is_floating_point<value_type>::value ||
|
||||
!options_type::test(option::overflow),
|
||||
"integer axis with integral type cannot have overflow");
|
||||
|
||||
public:
|
||||
constexpr integer() = default;
|
||||
|
||||
/** Construct over semi-open integer interval [start, stop).
|
||||
*
|
||||
* \param start first integer of covered range.
|
||||
* \param stop one past last integer of covered range.
|
||||
* \param meta description of the axis.
|
||||
*/
|
||||
integer(value_type start, value_type stop, metadata_type meta = {})
|
||||
: size_meta_(static_cast<index_type>(stop - start), std::move(meta)), min_(start) {
|
||||
if (stop <= start) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin.
|
||||
integer(const integer& src, index_type begin, index_type end, unsigned merge)
|
||||
: integer(src.value(begin), src.value(end), src.metadata()) {
|
||||
if (merge > 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot merge bins for integer axis"));
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
return index_impl(std::is_floating_point<value_type>(), x);
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
auto impl = [this](long x) {
|
||||
const auto i = x - min_;
|
||||
if (i >= 0) {
|
||||
const auto k = static_cast<axis::index_type>(i);
|
||||
if (k < size()) return std::make_pair(k, 0);
|
||||
const auto n = k - size() + 1;
|
||||
size_meta_.first() += n;
|
||||
return std::make_pair(k, -n);
|
||||
}
|
||||
const auto k = static_cast<axis::index_type>(
|
||||
detail::static_if<std::is_floating_point<value_type>>(
|
||||
[](auto x) { return std::floor(x); }, [](auto x) { return x; }, i));
|
||||
min_ += k;
|
||||
size_meta_.first() -= k;
|
||||
return std::make_pair(0, -k);
|
||||
};
|
||||
|
||||
return detail::static_if<std::is_floating_point<value_type>>(
|
||||
[this, impl](auto x) {
|
||||
if (std::isfinite(x)) return impl(static_cast<long>(std::floor(x)));
|
||||
// this->size() is workaround for gcc-5 bug
|
||||
return std::make_pair(x < 0 ? -1 : this->size(), 0);
|
||||
},
|
||||
impl, x);
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
value_type value(local_index_type i) const noexcept {
|
||||
if (!options_type::test(option::circular)) {
|
||||
if (i < 0) return detail::lowest<value_type>();
|
||||
if (i > size()) { return detail::highest<value_type>(); }
|
||||
}
|
||||
return min_ + i;
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept {
|
||||
return detail::static_if<std::is_floating_point<local_index_type>>(
|
||||
[this](auto idx) { return interval_view<integer>(*this, idx); },
|
||||
[this](auto idx) { return this->value(idx); }, idx);
|
||||
}
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept { return size_meta_.first(); }
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return size_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return size_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O>
|
||||
bool operator==(const integer<V, M, O>& o) const noexcept {
|
||||
return size() == o.size() && detail::relaxed_equal(metadata(), o.metadata()) &&
|
||||
min_ == o.min_;
|
||||
}
|
||||
|
||||
template <class V, class M, class O>
|
||||
bool operator!=(const integer<V, M, O>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
index_type index_impl(std::false_type, int x) const noexcept {
|
||||
const auto z = x - min_;
|
||||
if (options_type::test(option::circular))
|
||||
return static_cast<index_type>(z - std::floor(float(z) / size()) * size());
|
||||
if (z < size()) return z >= 0 ? z : -1;
|
||||
return size();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
index_type index_impl(std::true_type, T x) const noexcept {
|
||||
// need to handle NaN, cannot simply cast to int and call int-implementation
|
||||
const auto z = x - min_;
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z))
|
||||
return static_cast<index_type>(std::floor(z) - std::floor(z / size()) * size());
|
||||
} else if (z < size()) {
|
||||
return z >= 0 ? static_cast<index_type>(z) : -1;
|
||||
}
|
||||
return size();
|
||||
}
|
||||
|
||||
detail::compressed_pair<index_type, metadata_type> size_meta_{0};
|
||||
value_type min_{0};
|
||||
|
||||
template <class V, class M, class O>
|
||||
friend class integer;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
integer(T, T)->integer<detail::convert_integer<T, index_type>>;
|
||||
|
||||
template <class T>
|
||||
integer(T, T, const char*)->integer<detail::convert_integer<T, index_type>>;
|
||||
|
||||
template <class T, class M>
|
||||
integer(T, T, M)->integer<detail::convert_integer<T, index_type>, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
54
macx64/include/boost/histogram/axis/interval_view.hpp
Normal file
54
macx64/include/boost/histogram/axis/interval_view.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
// Copyright 2015-2019 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_INTERVAL_VIEW_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Lightweight bin view.
|
||||
|
||||
Represents the current bin interval.
|
||||
*/
|
||||
template <typename Axis>
|
||||
class interval_view {
|
||||
public:
|
||||
interval_view(const Axis& axis, int idx) : axis_(axis), idx_(idx) {}
|
||||
// avoid viewing a temporary that goes out of scope
|
||||
interval_view(Axis&& axis, int idx) = delete;
|
||||
|
||||
/// Return lower edge of bin.
|
||||
decltype(auto) lower() const noexcept { return axis_.value(idx_); }
|
||||
/// Return upper edge of bin.
|
||||
decltype(auto) upper() const noexcept { return axis_.value(idx_ + 1); }
|
||||
/// Return center of bin.
|
||||
decltype(auto) center() const noexcept { return axis_.value(idx_ + 0.5); }
|
||||
/// Return width of bin.
|
||||
decltype(auto) width() const noexcept { return upper() - lower(); }
|
||||
|
||||
template <typename BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
const Axis& axis_;
|
||||
const int idx_;
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
74
macx64/include/boost/histogram/axis/iterator.hpp
Normal file
74
macx64/include/boost/histogram/axis/iterator.hpp
Normal file
@@ -0,0 +1,74 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_ITERATOR_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_ITERATOR_HPP
|
||||
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <typename Axis>
|
||||
class iterator
|
||||
: public boost::iterator_adaptor<iterator<Axis>, int,
|
||||
decltype(std::declval<const Axis&>().bin(0)),
|
||||
std::random_access_iterator_tag,
|
||||
decltype(std::declval<const Axis&>().bin(0)), int> {
|
||||
public:
|
||||
explicit iterator(const Axis& axis, int idx)
|
||||
: iterator::iterator_adaptor_(idx), axis_(axis) {}
|
||||
|
||||
protected:
|
||||
bool equal(const iterator& other) const noexcept {
|
||||
return &axis_ == &other.axis_ && this->base() == other.base();
|
||||
}
|
||||
|
||||
decltype(auto) dereference() const { return axis_.bin(this->base()); }
|
||||
|
||||
private:
|
||||
const Axis& axis_;
|
||||
friend class boost::iterator_core_access;
|
||||
};
|
||||
|
||||
/// Uses CRTP to inject iterator logic into Derived.
|
||||
template <typename Derived>
|
||||
class iterator_mixin {
|
||||
public:
|
||||
using const_iterator = iterator<Derived>;
|
||||
using const_reverse_iterator = boost::reverse_iterator<const_iterator>;
|
||||
|
||||
/// Bin iterator to beginning of the axis (read-only).
|
||||
const_iterator begin() const noexcept {
|
||||
return const_iterator(*static_cast<const Derived*>(this), 0);
|
||||
}
|
||||
|
||||
/// Bin iterator to the end of the axis (read-only).
|
||||
const_iterator end() const noexcept {
|
||||
return const_iterator(*static_cast<const Derived*>(this),
|
||||
static_cast<const Derived*>(this)->size());
|
||||
}
|
||||
|
||||
/// Reverse bin iterator to the last entry of the axis (read-only).
|
||||
const_reverse_iterator rbegin() const noexcept {
|
||||
return boost::make_reverse_iterator(end());
|
||||
}
|
||||
|
||||
/// Reverse bin iterator to the end (read-only).
|
||||
const_reverse_iterator rend() const noexcept {
|
||||
return boost::make_reverse_iterator(begin());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
82
macx64/include/boost/histogram/axis/option.hpp
Normal file
82
macx64/include/boost/histogram/axis/option.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2015-2019 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
\file option.hpp Options for builtin axis types.
|
||||
|
||||
Options `circular` and `growth` are mutually exclusive.
|
||||
Options `circular` and `underflow` are mutually exclusive.
|
||||
*/
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
namespace option {
|
||||
|
||||
/// Holder of axis options.
|
||||
template <unsigned Bits>
|
||||
struct bitset : std::integral_constant<unsigned, Bits> {
|
||||
/// Returns true if all option flags in the argument are set and false otherwise.
|
||||
template <unsigned B>
|
||||
static constexpr auto test(bitset<B>) {
|
||||
return std::integral_constant<bool, static_cast<bool>(Bits & B)>{};
|
||||
}
|
||||
};
|
||||
|
||||
/// Set union of the axis option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator|(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 | B2)>{};
|
||||
}
|
||||
|
||||
/// Set intersection of the option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator&(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 & B2)>{};
|
||||
}
|
||||
|
||||
/// Set difference of the option arguments.
|
||||
template <unsigned B1, unsigned B2>
|
||||
constexpr auto operator-(bitset<B1>, bitset<B2>) {
|
||||
return bitset<(B1 & ~B2)>{};
|
||||
}
|
||||
|
||||
/**
|
||||
Single option flag.
|
||||
|
||||
@tparam Pos position of the bit in the set.
|
||||
*/
|
||||
template <unsigned Pos>
|
||||
struct bit : bitset<(1 << Pos)> {};
|
||||
|
||||
/// All options off.
|
||||
using none_t = bitset<0>;
|
||||
constexpr none_t none{}; ///< Instance of `none_t`.
|
||||
/// Axis has an underflow bin. Mutually exclusive with `circular`.
|
||||
using underflow_t = bit<0>;
|
||||
constexpr underflow_t underflow{}; ///< Instance of `underflow_t`.
|
||||
/// Axis has overflow bin.
|
||||
using overflow_t = bit<1>;
|
||||
constexpr overflow_t overflow{}; ///< Instance of `overflow_t`.
|
||||
/// Axis is circular. Mutually exclusive with `growth` and `underflow`.
|
||||
using circular_t = bit<2>;
|
||||
constexpr circular_t circular{}; ///< Instance of `circular_t`.
|
||||
/// Axis can grow. Mutually exclusive with `circular`.
|
||||
using growth_t = bit<3>;
|
||||
constexpr growth_t growth{}; ///< Instance of `growth_t`.
|
||||
|
||||
} // namespace option
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
193
macx64/include/boost/histogram/axis/ostream.hpp
Normal file
193
macx64/include/boost/histogram/axis/ostream.hpp
Normal file
@@ -0,0 +1,193 @@
|
||||
// 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)
|
||||
//
|
||||
// String representations here evaluate correctly in Python.
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_OSTREAM_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/regular.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <iomanip>
|
||||
#include <iosfwd>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
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=" << boost::core::demangled_name(BOOST_CORE_TYPEID(T));
|
||||
},
|
||||
t);
|
||||
}
|
||||
|
||||
template <class OStream>
|
||||
void stream_options(OStream& os, const unsigned bits) {
|
||||
os << ", options=";
|
||||
bool first = true;
|
||||
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(x) \
|
||||
if (bits & axis::option::x) { \
|
||||
if (first) \
|
||||
first = false; \
|
||||
else { \
|
||||
os << " | "; \
|
||||
} \
|
||||
os << #x; \
|
||||
}
|
||||
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(underflow);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(overflow);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(circular);
|
||||
BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM(growth);
|
||||
|
||||
#undef BOOST_HISTOGRAM_AXIS_OPTION_OSTREAM
|
||||
|
||||
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 {
|
||||
|
||||
template <class T>
|
||||
class polymorphic_bin;
|
||||
|
||||
template <class... Ts>
|
||||
std::basic_ostream<Ts...>& operator<<(std::basic_ostream<Ts...>& os, const null_type&) {
|
||||
return os; // do nothing
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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() << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
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;
|
||||
}
|
||||
|
||||
template <class... Ts, class... Us>
|
||||
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));
|
||||
os << (i == (a.size() - 1) ? "" : ", ");
|
||||
}
|
||||
detail::stream_metadata(os, a.metadata());
|
||||
detail::stream_options(os, a.options());
|
||||
os << ")";
|
||||
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 = detail::remove_cvref_t<decltype(x)>;
|
||||
detail::static_if<detail::is_streamable<A>>(
|
||||
[&os](const auto& x) { os << x; },
|
||||
[](const auto&) {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(A)),
|
||||
" is not streamable")));
|
||||
},
|
||||
x);
|
||||
},
|
||||
v);
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
|
||||
#endif
|
||||
88
macx64/include/boost/histogram/axis/polymorphic_bin.hpp
Normal file
88
macx64/include/boost/histogram/axis/polymorphic_bin.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright 2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_POLYMORPHIC_BIN_HPP
|
||||
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Holds the bin data of a axis::variant.
|
||||
|
||||
The interface is a superset of the `value_bin_view` and `interval_bin_view`
|
||||
classes. The methods value() and lower() return the same number. For a value bin,
|
||||
upper() and lower() and center() return the same number, width() returns zero.
|
||||
|
||||
This is not a view like interval_bin_view or value_bin_view for two reasons.
|
||||
- Sequential calls to lower() and upper() would have to each loop through
|
||||
the variant types. This is likely to be slower than filling all the data in
|
||||
one loop.
|
||||
- polymorphic_bin may be created from a temporary instance of axis::variant,
|
||||
like in the call histogram::axis(0). Storing a reference to the axis would
|
||||
result in a dangling reference. Rather than specialing the code to handle
|
||||
this, it seems easier to just use a value instead of a view here.
|
||||
*/
|
||||
template <typename RealType>
|
||||
class polymorphic_bin {
|
||||
using value_type = RealType;
|
||||
|
||||
public:
|
||||
polymorphic_bin(value_type lower, value_type upper)
|
||||
: lower_or_value_(lower), upper_(upper) {}
|
||||
|
||||
/// Implicitly convert to bin value (for axis with discrete values).
|
||||
operator const value_type&() const noexcept { return lower_or_value_; }
|
||||
|
||||
/// Return lower edge of bin.
|
||||
value_type lower() const noexcept { return lower_or_value_; }
|
||||
/// Return upper edge of bin.
|
||||
value_type upper() const noexcept { return upper_; }
|
||||
/// Return center of bin.
|
||||
value_type center() const noexcept { return 0.5 * (lower() + upper()); }
|
||||
/// Return width of bin.
|
||||
value_type width() const noexcept { return upper() - lower(); }
|
||||
|
||||
template <typename BinType>
|
||||
bool operator==(const BinType& rhs) const noexcept {
|
||||
return equal_impl(detail::has_method_lower<BinType>(), rhs);
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool operator!=(const BinType& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
/// Return true if bin is discrete.
|
||||
bool is_discrete() const noexcept { return lower_or_value_ == upper_; }
|
||||
|
||||
private:
|
||||
bool equal_impl(std::true_type, const polymorphic_bin& rhs) const noexcept {
|
||||
return lower_or_value_ == rhs.lower_or_value_ && upper_ == rhs.upper_;
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool equal_impl(std::true_type, const BinType& rhs) const noexcept {
|
||||
return lower() == rhs.lower() && upper() == rhs.upper();
|
||||
}
|
||||
|
||||
template <typename BinType>
|
||||
bool equal_impl(std::false_type, const BinType& rhs) const noexcept {
|
||||
return is_discrete() && static_cast<value_type>(*this) == rhs;
|
||||
}
|
||||
|
||||
const value_type lower_or_value_, upper_;
|
||||
};
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
359
macx64/include/boost/histogram/axis/regular.hpp
Normal file
359
macx64/include/boost/histogram/axis/regular.hpp
Normal file
@@ -0,0 +1,359 @@
|
||||
// Copyright 2015-2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_REGULAR_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_REGULAR_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/utility.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
namespace transform {
|
||||
|
||||
/// Identity transform for equidistant bins.
|
||||
struct id {
|
||||
/// Pass-through.
|
||||
template <typename T>
|
||||
static T forward(T&& x) noexcept {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
|
||||
/// Pass-through.
|
||||
template <typename T>
|
||||
static T inverse(T&& x) noexcept {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
};
|
||||
|
||||
/// Log transform for equidistant bins in log-space.
|
||||
struct log {
|
||||
/// Returns log(x) of external value x.
|
||||
template <typename T>
|
||||
static T forward(T x) {
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
/// Returns exp(x) for internal value x.
|
||||
template <typename T>
|
||||
static T inverse(T x) {
|
||||
return std::exp(x);
|
||||
}
|
||||
};
|
||||
|
||||
/// Sqrt transform for equidistant bins in sqrt-space.
|
||||
struct sqrt {
|
||||
/// Returns sqrt(x) of external value x.
|
||||
template <typename T>
|
||||
static T forward(T x) {
|
||||
return std::sqrt(x);
|
||||
}
|
||||
|
||||
/// Returns x^2 of internal value x.
|
||||
template <typename T>
|
||||
static T inverse(T x) {
|
||||
return x * x;
|
||||
}
|
||||
};
|
||||
|
||||
/// Pow transform for equidistant bins in pow-space.
|
||||
struct pow {
|
||||
double power = 1; /**< power index */
|
||||
|
||||
/// Make transform with index p.
|
||||
explicit pow(double p) : power(p) {}
|
||||
pow() = default;
|
||||
|
||||
/// Returns pow(x, power) of external value x.
|
||||
template <typename T>
|
||||
auto forward(T x) const {
|
||||
return std::pow(x, power);
|
||||
}
|
||||
|
||||
/// Returns pow(x, 1/power) of external value x.
|
||||
template <typename T>
|
||||
auto inverse(T x) const {
|
||||
return std::pow(x, 1.0 / power);
|
||||
}
|
||||
|
||||
bool operator==(const pow& o) const noexcept { return power == o.power; }
|
||||
};
|
||||
|
||||
} // namespace transform
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
// Type envelope to mark value as step size
|
||||
template <typename T>
|
||||
struct step_type {
|
||||
T value;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
Helper function to mark argument as step size.
|
||||
*/
|
||||
template <typename T>
|
||||
auto step(T&& t) {
|
||||
return step_type<T&&>{std::forward<T>(t)};
|
||||
}
|
||||
|
||||
/**
|
||||
Axis for equidistant intervals on the real line.
|
||||
|
||||
The most common binning strategy. Very fast. Binning is a O(1) operation.
|
||||
|
||||
@tparam Value input value type, must be floating point.
|
||||
@tparam Transform builtin or user-defined transform type.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option (all values allowed).
|
||||
*/
|
||||
template <class Value, class Transform, class MetaData, class Options>
|
||||
class regular : public iterator_mixin<regular<Value, Transform, MetaData, Options>>,
|
||||
protected detail::replace_default<Transform, transform::id> {
|
||||
using value_type = Value;
|
||||
using transform_type = detail::replace_default<Transform, transform::id>;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
|
||||
using unit_type = detail::get_unit_type<value_type>;
|
||||
using internal_value_type = detail::get_scale_type<value_type>;
|
||||
static_assert(std::is_floating_point<internal_value_type>::value,
|
||||
"variable axis requires floating point type");
|
||||
|
||||
public:
|
||||
constexpr regular() = default;
|
||||
|
||||
/** Construct n bins over real transformed range [start, stop).
|
||||
*
|
||||
* @param trans transform instance to use.
|
||||
* @param n number of bins.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop high edge of last bin.
|
||||
* @param meta description of the axis (optional).
|
||||
*/
|
||||
regular(transform_type trans, unsigned n, value_type start, value_type stop,
|
||||
metadata_type meta = {})
|
||||
: transform_type(std::move(trans))
|
||||
, size_meta_(static_cast<index_type>(n), std::move(meta))
|
||||
, min_(this->forward(detail::get_scale(start)))
|
||||
, delta_(this->forward(detail::get_scale(stop)) - min_) {
|
||||
if (size() == 0) BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
if (!std::isfinite(min_) || !std::isfinite(delta_))
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("forward transform of start or stop invalid"));
|
||||
if (delta_ == 0)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("range of axis is zero"));
|
||||
}
|
||||
|
||||
/** Construct n bins over real range [start, stop).
|
||||
*
|
||||
* @param n number of bins.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop high edge of last bin.
|
||||
* @param meta description of the axis (optional).
|
||||
*/
|
||||
regular(unsigned n, value_type start, value_type stop, metadata_type meta = {})
|
||||
: regular({}, n, start, stop, std::move(meta)) {}
|
||||
|
||||
/** Construct bins with the given step size over real transformed range
|
||||
* [start, stop).
|
||||
*
|
||||
* @param trans transform instance to use.
|
||||
* @param step width of a single bin.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop upper limit of high edge of last bin (see below).
|
||||
* @param meta description of the axis (optional).
|
||||
*
|
||||
* The axis computes the number of bins as n = abs(stop - start) / step,
|
||||
* rounded down. This means that stop is an upper limit to the actual value
|
||||
* (start + n * step).
|
||||
*/
|
||||
template <class T>
|
||||
regular(transform_type trans, const step_type<T>& step, value_type start,
|
||||
value_type stop, metadata_type meta = {})
|
||||
: regular(trans, static_cast<index_type>(std::abs(stop - start) / step.value),
|
||||
start,
|
||||
start + static_cast<index_type>(std::abs(stop - start) / step.value) *
|
||||
step.value,
|
||||
std::move(meta)) {}
|
||||
|
||||
/** Construct bins with the given step size over real range [start, stop).
|
||||
*
|
||||
* @param step width of a single bin.
|
||||
* @param start low edge of first bin.
|
||||
* @param stop upper limit of high edge of last bin (see below).
|
||||
* @param meta description of the axis (optional).
|
||||
*
|
||||
* The axis computes the number of bins as n = abs(stop - start) / step,
|
||||
* rounded down. This means that stop is an upper limit to the actual value
|
||||
* (start + n * step).
|
||||
*/
|
||||
template <class T>
|
||||
regular(const step_type<T>& step, value_type start, value_type stop,
|
||||
metadata_type meta = {})
|
||||
: regular({}, step, start, stop, std::move(meta)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin (not for users).
|
||||
regular(const regular& src, index_type begin, index_type end, unsigned merge)
|
||||
: regular(src.transform(), (end - begin) / merge, src.value(begin), src.value(end),
|
||||
src.metadata()) {
|
||||
BOOST_ASSERT((end - begin) % merge == 0);
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
}
|
||||
|
||||
/// Return instance of the transform type.
|
||||
const transform_type& transform() const noexcept { return *this; }
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
// Runs in hot loop, please measure impact of changes
|
||||
auto z = (this->forward(x / unit_type{}) - min_) / delta_;
|
||||
if (options_type::test(option::circular)) {
|
||||
if (std::isfinite(z)) {
|
||||
z -= std::floor(z);
|
||||
return static_cast<index_type>(z * size());
|
||||
}
|
||||
} else {
|
||||
if (z < 1) {
|
||||
if (z >= 0)
|
||||
return static_cast<index_type>(z * size());
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return size(); // also returned if x is NaN
|
||||
}
|
||||
|
||||
/// Returns index and shift (if axis has grown) for the passed argument.
|
||||
auto update(value_type x) noexcept {
|
||||
BOOST_ASSERT(options_type::test(option::growth));
|
||||
const auto z = (this->forward(x / unit_type{}) - min_) / delta_;
|
||||
if (z < 1) { // don't use i here!
|
||||
if (z >= 0) {
|
||||
const auto i = static_cast<axis::index_type>(z * size());
|
||||
return std::make_pair(i, 0);
|
||||
}
|
||||
if (z != -std::numeric_limits<internal_value_type>::infinity()) {
|
||||
const auto stop = min_ + delta_;
|
||||
const auto i = static_cast<axis::index_type>(std::floor(z * size()));
|
||||
min_ += i * (delta_ / size());
|
||||
delta_ = stop - min_;
|
||||
size_meta_.first() -= i;
|
||||
return std::make_pair(0, -i);
|
||||
}
|
||||
// z is -infinity
|
||||
return std::make_pair(-1, 0);
|
||||
}
|
||||
// z either beyond range, infinite, or NaN
|
||||
if (z < std::numeric_limits<internal_value_type>::infinity()) {
|
||||
const auto i = static_cast<axis::index_type>(z * size());
|
||||
const auto n = i - size() + 1;
|
||||
delta_ /= size();
|
||||
delta_ *= size() + n;
|
||||
size_meta_.first() += n;
|
||||
return std::make_pair(i, -n);
|
||||
}
|
||||
// z either infinite or NaN
|
||||
return std::make_pair(size(), 0);
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
value_type value(real_index_type i) const noexcept {
|
||||
auto z = i / size();
|
||||
if (!options_type::test(option::circular) && z < 0.0)
|
||||
z = -std::numeric_limits<internal_value_type>::infinity() * delta_;
|
||||
else if (options_type::test(option::circular) || z <= 1.0)
|
||||
z = (1.0 - z) * min_ + z * (min_ + delta_);
|
||||
else {
|
||||
z = std::numeric_limits<internal_value_type>::infinity() * delta_;
|
||||
}
|
||||
return static_cast<value_type>(this->inverse(z) * unit_type());
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
decltype(auto) bin(index_type idx) const noexcept {
|
||||
return interval_view<regular>(*this, idx);
|
||||
}
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept { return size_meta_.first(); }
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return size_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return size_meta_.second(); }
|
||||
|
||||
template <class V, class T, class M, class O>
|
||||
bool operator==(const regular<V, T, M, O>& o) const noexcept {
|
||||
return detail::relaxed_equal(transform(), o.transform()) && size() == o.size() &&
|
||||
detail::relaxed_equal(metadata(), o.metadata()) && min_ == o.min_ &&
|
||||
delta_ == o.delta_;
|
||||
}
|
||||
template <class V, class T, class M, class O>
|
||||
bool operator!=(const regular<V, T, M, O>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<index_type, metadata_type> size_meta_{0};
|
||||
internal_value_type min_{0}, delta_{1};
|
||||
|
||||
template <class V, class T, class M, class O>
|
||||
friend class regular;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class T>
|
||||
regular(unsigned, T, T)->regular<detail::convert_integer<T, double>>;
|
||||
|
||||
template <class T>
|
||||
regular(unsigned, T, T, const char*)->regular<detail::convert_integer<T, double>>;
|
||||
|
||||
template <class T, class M>
|
||||
regular(unsigned, T, T, M)->regular<detail::convert_integer<T, double>, transform::id, M>;
|
||||
|
||||
template <class Tr, class T>
|
||||
regular(Tr, unsigned, T, T)->regular<detail::convert_integer<T, double>, Tr>;
|
||||
|
||||
template <class Tr, class T>
|
||||
regular(Tr, unsigned, T, T, const char*)->regular<detail::convert_integer<T, double>, Tr>;
|
||||
|
||||
template <class Tr, class T, class M>
|
||||
regular(Tr, unsigned, T, T, M)->regular<detail::convert_integer<T, double>, Tr, M>;
|
||||
|
||||
#endif
|
||||
|
||||
template <class Value = double, class MetaData = use_default, class Options = use_default>
|
||||
using circular = regular<Value, transform::id, MetaData,
|
||||
decltype(detail::replace_default<Options, option::overflow_t>{} |
|
||||
option::circular)>;
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
283
macx64/include/boost/histogram/axis/traits.hpp
Normal file
283
macx64/include/boost/histogram/axis/traits.hpp
Normal file
@@ -0,0 +1,283 @@
|
||||
// Copyright 2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_TRAITS_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_TRAITS_HPP
|
||||
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace detail {
|
||||
|
||||
template <class T>
|
||||
using static_options_impl = axis::option::bitset<T::options()>;
|
||||
|
||||
template <class FIntArg, class FDoubleArg, class T>
|
||||
decltype(auto) value_method_switch(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
|
||||
return static_if<has_method_value<T>>(
|
||||
[](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
},
|
||||
[](FIntArg&&, FDoubleArg&&, const auto& t) -> double {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(A)), " has no value method")));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return double{};
|
||||
#endif
|
||||
},
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
}
|
||||
|
||||
template <class R1, class R2, class FIntArg, class FDoubleArg, class T>
|
||||
R2 value_method_switch_with_return_type(FIntArg&& iarg, FDoubleArg&& darg, const T& t) {
|
||||
return static_if<has_method_value_with_convertible_return_type<T, R1>>(
|
||||
[](FIntArg&& iarg, FDoubleArg&& darg, const auto& t) -> R2 {
|
||||
using A = remove_cvref_t<decltype(t)>;
|
||||
return static_if<std::is_same<arg_type<decltype(&A::value), 0>, int>>(
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
},
|
||||
[](FIntArg&&, FDoubleArg&&, const auto&) -> R2 {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(T)),
|
||||
" has no value method or return type is not convertible to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(R1)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
// conjure a value out of thin air to satisfy syntactic requirement
|
||||
return *reinterpret_cast<R2*>(0);
|
||||
#endif
|
||||
},
|
||||
std::forward<FIntArg>(iarg), std::forward<FDoubleArg>(darg), t);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
namespace axis {
|
||||
namespace traits {
|
||||
|
||||
/** Returns reference to metadata of an axis.
|
||||
|
||||
If the expression x.metadata() for an axis instance `x` (maybe const) is valid, return
|
||||
the result. Otherwise, return a reference to a static instance of
|
||||
boost::histogram::axis::null_type.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) metadata(Axis&& axis) noexcept {
|
||||
return detail::static_if<
|
||||
detail::has_method_metadata<const detail::remove_cvref_t<Axis>>>(
|
||||
[](auto&& a) -> decltype(auto) { return a.metadata(); },
|
||||
[](auto &&) -> detail::copy_qualifiers<Axis, null_type> {
|
||||
static null_type m;
|
||||
return m;
|
||||
},
|
||||
std::forward<Axis>(axis));
|
||||
}
|
||||
|
||||
/** Generates static axis option type for axis type.
|
||||
|
||||
WARNING: Doxygen does not render the synopsis correctly. This is a templated using
|
||||
directive, which accepts axis type and returns boost::histogram::axis::option::bitset.
|
||||
|
||||
If Axis::options() is valid and constexpr, return the corresponding option type.
|
||||
Otherwise, return boost::histogram::axis::option::growth_t, if the axis has a method
|
||||
`update`, else return boost::histogram::axis::option::none_t.
|
||||
|
||||
@tparam Axis axis type
|
||||
*/
|
||||
template <class Axis>
|
||||
using static_options = detail::mp_eval_or<
|
||||
mp11::mp_if<detail::has_method_update<detail::remove_cvref_t<Axis>>, option::growth_t,
|
||||
option::none_t>,
|
||||
detail::static_options_impl, detail::remove_cvref_t<Axis>>;
|
||||
|
||||
/** Returns axis options as unsigned integer.
|
||||
|
||||
If axis.options() is valid, return the result. Otherwise, return
|
||||
boost::histogram::axis::traits::static_options<decltype(axis)>::value.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
constexpr unsigned options(const Axis& axis) noexcept {
|
||||
// cannot reuse static_options here, because this should also work for axis::variant
|
||||
return detail::static_if<detail::has_method_options<Axis>>(
|
||||
[](const auto& a) { return a.options(); },
|
||||
[](const auto&) { return static_options<Axis>::value; }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis size plus any extra bins for under- and overflow.
|
||||
|
||||
@param axis any axis instance
|
||||
*/
|
||||
template <class Axis>
|
||||
constexpr index_type extent(const Axis& axis) noexcept {
|
||||
const auto opt = options(axis);
|
||||
return axis.size() + (opt & option::underflow ? 1 : 0) +
|
||||
(opt & option::overflow ? 1 : 0);
|
||||
}
|
||||
|
||||
/** Returns axis value for index.
|
||||
|
||||
If the axis has no `value` method, throw std::runtime_error. If the method exists and
|
||||
accepts a floating point index, pass the index and return the result. If the method
|
||||
exists but accepts only integer indices, cast the floating point index to int, pass this
|
||||
index and return the result.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index floating point axis index
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) value(const Axis& axis, real_index_type index) {
|
||||
return detail::value_method_switch(
|
||||
[index](const auto& a) { return a.value(static_cast<int>(index)); },
|
||||
[index](const auto& a) { return a.value(index); }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis value for index if it is convertible to target type or throws.
|
||||
|
||||
Like boost::histogram::axis::traits::value, but converts the result into the requested
|
||||
return type. If the conversion is not possible, throws std::runtime_error.
|
||||
|
||||
@tparam Result requested return type
|
||||
@tparam Axis axis type
|
||||
@param axis any axis instance
|
||||
@param index floating point axis index
|
||||
*/
|
||||
template <class Result, class Axis>
|
||||
Result value_as(const Axis& axis, real_index_type index) {
|
||||
return detail::value_method_switch_with_return_type<Result, Result>(
|
||||
[index](const auto& a) {
|
||||
return static_cast<Result>(a.value(static_cast<int>(index)));
|
||||
},
|
||||
[index](const auto& a) { return static_cast<Result>(a.value(index)); }, axis);
|
||||
}
|
||||
|
||||
/** Returns axis index for value.
|
||||
|
||||
Throws std::invalid_argument if the value argument is not implicitly convertible.
|
||||
|
||||
@param axis any axis instance
|
||||
@param value argument to be passed to `index` method
|
||||
*/
|
||||
template <class Axis, class U>
|
||||
auto index(const Axis& axis, const U& value) {
|
||||
using V = detail::arg_type<decltype(&Axis::index)>;
|
||||
return detail::static_if<std::is_convertible<U, V>>(
|
||||
[&value](const auto& axis) {
|
||||
using A = detail::remove_cvref_t<decltype(axis)>;
|
||||
using V2 = detail::arg_type<decltype(&A::index)>;
|
||||
return axis.index(static_cast<V2>(value));
|
||||
},
|
||||
[](const Axis&) -> index_type {
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
|
||||
": cannot convert argument of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return index_type{};
|
||||
#endif
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
/// @copydoc index(const Axis&, const U& value)
|
||||
template <class... Ts, class U>
|
||||
auto index(const variant<Ts...>& axis, const U& value) {
|
||||
return axis.index(value);
|
||||
}
|
||||
|
||||
/** Returns pair of axis index and shift for the value argument.
|
||||
|
||||
Throws `std::invalid_argument` if the value argument is not implicitly convertible to
|
||||
the argument expected by the `index` method. If the result of
|
||||
boost::histogram::axis::traits::static_options<decltype(axis)> has the growth flag set,
|
||||
call `update` method with the argument and return the result. Otherwise, call `index`
|
||||
and return the pair of the result and a zero shift.
|
||||
|
||||
@param axis any axis instance
|
||||
@param value argument to be passed to `update` or `index` method
|
||||
*/
|
||||
template <class Axis, class U>
|
||||
std::pair<int, int> update(Axis& axis, const U& value) {
|
||||
using V = detail::arg_type<decltype(&Axis::index)>;
|
||||
return detail::static_if<std::is_convertible<U, V>>(
|
||||
[&value](auto& a) {
|
||||
using A = detail::remove_cvref_t<decltype(a)>;
|
||||
return detail::static_if_c<static_options<A>::test(option::growth)>(
|
||||
[&value](auto& a) { return a.update(value); },
|
||||
[&value](auto& a) { return std::make_pair(a.index(value), 0); }, a);
|
||||
},
|
||||
[](Axis&) -> std::pair<index_type, index_type> {
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(Axis)),
|
||||
": cannot convert argument of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)), " to ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(V)))));
|
||||
#ifndef _MSC_VER // msvc warns about unreachable return
|
||||
return std::make_pair(index_type{}, index_type{});
|
||||
#endif
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
/// @copydoc update(Axis& axis, const U& value)
|
||||
template <class... Ts, class U>
|
||||
auto update(variant<Ts...>& axis, const U& value) {
|
||||
return axis.update(value);
|
||||
}
|
||||
|
||||
/** Returns bin width at axis index.
|
||||
|
||||
If the axis has no `value` method, throw std::runtime_error. If the method exists and
|
||||
accepts a floating point index, return the result of `axis.value(index + 1) -
|
||||
axis.value(index)`. If the method exists but accepts only integer indices, return 0.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index bin index
|
||||
*/
|
||||
template <class Axis>
|
||||
decltype(auto) width(const Axis& axis, index_type index) {
|
||||
return detail::value_method_switch(
|
||||
[](const auto&) { return 0; },
|
||||
[index](const auto& a) { return a.value(index + 1) - a.value(index); }, axis);
|
||||
}
|
||||
|
||||
/** Returns bin width at axis index.
|
||||
|
||||
Like boost::histogram::axis::traits::width, but converts the result into the requested
|
||||
return type. If the conversion is not possible, throw std::runtime_error.
|
||||
|
||||
@param axis any axis instance
|
||||
@param index bin index
|
||||
*/
|
||||
template <class Result, class Axis>
|
||||
Result width_as(const Axis& axis, index_type index) {
|
||||
return detail::value_method_switch_with_return_type<Result, Result>(
|
||||
[](const auto&) { return Result{}; },
|
||||
[index](const auto& a) {
|
||||
return static_cast<Result>(a.value(index + 1) - a.value(index));
|
||||
},
|
||||
axis);
|
||||
}
|
||||
|
||||
} // namespace traits
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
242
macx64/include/boost/histogram/axis/variable.hpp
Normal file
242
macx64/include/boost/histogram/axis/variable.hpp
Normal file
@@ -0,0 +1,242 @@
|
||||
// Copyright 2015-2018 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_VARIABLE_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_VARIABLE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/histogram/axis/interval_view.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/option.hpp>
|
||||
#include <boost/histogram/detail/compressed_pair.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
/**
|
||||
Axis for non-equidistant bins on the real line.
|
||||
|
||||
Binning is a O(log(N)) operation. If speed matters and the problem domain
|
||||
allows it, prefer a regular axis, possibly with a transform.
|
||||
|
||||
@tparam Value input value type, must be floating point.
|
||||
@tparam MetaData type to store meta data.
|
||||
@tparam Options see boost::histogram::axis::option (all values allowed).
|
||||
@tparam Allocator allocator to use for dynamic memory management.
|
||||
*/
|
||||
template <class Value, class MetaData, class Options, class Allocator>
|
||||
class variable : public iterator_mixin<variable<Value, MetaData, Options, Allocator>> {
|
||||
static_assert(std::is_floating_point<Value>::value,
|
||||
"variable axis requires floating point type");
|
||||
|
||||
using value_type = Value;
|
||||
using metadata_type = detail::replace_default<MetaData, std::string>;
|
||||
using options_type =
|
||||
detail::replace_default<Options, decltype(option::underflow | option::overflow)>;
|
||||
using allocator_type = Allocator;
|
||||
using vec_type = std::vector<Value, allocator_type>;
|
||||
|
||||
public:
|
||||
explicit variable(allocator_type alloc = {}) : vec_meta_(std::move(alloc)) {}
|
||||
|
||||
/** Construct from iterator range of bin edges.
|
||||
*
|
||||
* \param begin begin of edge sequence.
|
||||
* \param end end of edge sequence.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class It, class = detail::requires_iterator<It>>
|
||||
variable(It begin, It end, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: vec_meta_(vec_type(std::move(alloc)), std::move(meta)) {
|
||||
if (std::distance(begin, end) <= 1)
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("bins > 0 required"));
|
||||
|
||||
auto& v = vec_meta_.first();
|
||||
v.reserve(std::distance(begin, end));
|
||||
v.emplace_back(*begin++);
|
||||
while (begin != end) {
|
||||
if (*begin <= v.back())
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("input sequence must be strictly ascending"));
|
||||
v.emplace_back(*begin++);
|
||||
}
|
||||
}
|
||||
|
||||
/** Construct variable axis from iterable range of bin edges.
|
||||
*
|
||||
* \param iterable iterable range of bin edges.
|
||||
* \param meta description of the axis.
|
||||
* \param alloc allocator instance to use.
|
||||
*/
|
||||
template <class U, class = detail::requires_iterable<U>>
|
||||
variable(const U& iterable, metadata_type meta = {}, allocator_type alloc = {})
|
||||
: variable(std::begin(iterable), std::end(iterable), std::move(meta),
|
||||
std::move(alloc)) {}
|
||||
|
||||
/** Construct variable axis from initializer list of bin edges.
|
||||
*
|
||||
* @param list `std::initializer_list` of bin edges.
|
||||
* @param meta description of the axis.
|
||||
* @param alloc allocator instance to use.
|
||||
*/
|
||||
template <class U>
|
||||
variable(std::initializer_list<U> list, metadata_type meta = {},
|
||||
allocator_type alloc = {})
|
||||
: variable(list.begin(), list.end(), std::move(meta), std::move(alloc)) {}
|
||||
|
||||
/// Constructor used by algorithm::reduce to shrink and rebin (not for users).
|
||||
variable(const variable& src, index_type begin, index_type end, unsigned merge)
|
||||
: vec_meta_(vec_type(src.get_allocator()), src.metadata()) {
|
||||
BOOST_ASSERT((end - begin) % merge == 0);
|
||||
if (options_type::test(option::circular) && !(begin == 0 && end == src.size()))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("cannot shrink circular axis"));
|
||||
auto& vec = vec_meta_.first();
|
||||
vec.reserve((end - begin) / merge);
|
||||
const auto beg = src.vec_meta_.first().begin();
|
||||
for (index_type i = begin; i <= end; i += merge) vec.emplace_back(*(beg + i));
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
index_type index(value_type x) const noexcept {
|
||||
const auto& v = vec_meta_.first();
|
||||
if (options_type::test(option::circular)) {
|
||||
const auto a = v[0];
|
||||
const auto b = v[size()];
|
||||
x -= std::floor((x - a) / (b - a)) * (b - a);
|
||||
}
|
||||
return static_cast<index_type>(std::upper_bound(v.begin(), v.end(), x) - v.begin() -
|
||||
1);
|
||||
}
|
||||
|
||||
auto update(value_type x) noexcept {
|
||||
const auto i = index(x);
|
||||
if (std::isfinite(x)) {
|
||||
auto& vec = vec_meta_.first();
|
||||
if (0 <= i) {
|
||||
if (i < size()) return std::make_pair(i, 0);
|
||||
const auto d = value(size()) - value(size() - 0.5);
|
||||
x = std::nextafter(x, std::numeric_limits<value_type>::max());
|
||||
x = std::max(x, vec.back() + d);
|
||||
vec.push_back(x);
|
||||
return std::make_pair(i, -1);
|
||||
}
|
||||
const auto d = value(0.5) - value(0);
|
||||
x = std::min(x, value(0) - d);
|
||||
vec.insert(vec.begin(), x);
|
||||
return std::make_pair(0, -i);
|
||||
}
|
||||
return std::make_pair(x < 0 ? -1 : size(), 0);
|
||||
}
|
||||
|
||||
/// Return value for fractional index argument.
|
||||
value_type value(real_index_type i) const noexcept {
|
||||
const auto& v = vec_meta_.first();
|
||||
if (options_type::test(option::circular)) {
|
||||
auto shift = std::floor(i / size());
|
||||
i -= shift * size();
|
||||
double z;
|
||||
const auto k = static_cast<index_type>(std::modf(i, &z));
|
||||
const auto a = v[0];
|
||||
const auto b = v[size()];
|
||||
return (1.0 - z) * v[k] + z * v[k + 1] + shift * (b - a);
|
||||
}
|
||||
if (i < 0) return detail::lowest<value_type>();
|
||||
if (i == size()) return v.back();
|
||||
if (i > size()) return detail::highest<value_type>();
|
||||
const auto k = static_cast<index_type>(i); // precond: i >= 0
|
||||
const real_index_type z = i - k;
|
||||
return (1.0 - z) * v[k] + z * v[k + 1];
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
auto bin(index_type idx) const noexcept { return interval_view<variable>(*this, idx); }
|
||||
|
||||
/// Returns the number of bins, without over- or underflow.
|
||||
index_type size() const noexcept {
|
||||
return static_cast<index_type>(vec_meta_.first().size()) - 1;
|
||||
}
|
||||
/// Returns the options.
|
||||
static constexpr unsigned options() noexcept { return options_type::value; }
|
||||
/// Returns reference to metadata.
|
||||
metadata_type& metadata() noexcept { return vec_meta_.second(); }
|
||||
/// Returns reference to const metadata.
|
||||
const metadata_type& metadata() const noexcept { return vec_meta_.second(); }
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator==(const variable<V, M, O, A>& o) const noexcept {
|
||||
const auto& a = vec_meta_.first();
|
||||
const auto& b = o.vec_meta_.first();
|
||||
return std::equal(a.begin(), a.end(), b.begin(), b.end()) &&
|
||||
detail::relaxed_equal(metadata(), o.metadata());
|
||||
}
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
bool operator!=(const variable<V, M, O, A>& o) const noexcept {
|
||||
return !operator==(o);
|
||||
}
|
||||
|
||||
/// Return allocator instance.
|
||||
auto get_allocator() const { return vec_meta_.first().get_allocator(); }
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive&, unsigned);
|
||||
|
||||
private:
|
||||
detail::compressed_pair<vec_type, metadata_type> vec_meta_;
|
||||
|
||||
template <class V, class M, class O, class A>
|
||||
friend class variable;
|
||||
};
|
||||
|
||||
#if __cpp_deduction_guides >= 201606
|
||||
|
||||
template <class U, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>)->variable<T>;
|
||||
|
||||
template <class U, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>, const char*)->variable<T>;
|
||||
|
||||
template <class U, class M, class T = detail::convert_integer<U, double>>
|
||||
variable(std::initializer_list<U>, M)->variable<T, M>;
|
||||
|
||||
template <
|
||||
class Iterable,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable)->variable<T>;
|
||||
|
||||
template <
|
||||
class Iterable,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable, const char*)->variable<T>;
|
||||
|
||||
template <
|
||||
class Iterable, class M,
|
||||
class T = detail::convert_integer<
|
||||
detail::remove_cvref_t<decltype(*std::begin(std::declval<Iterable&>()))>, double>>
|
||||
variable(Iterable, M)->variable<T, M>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
299
macx64/include/boost/histogram/axis/variant.hpp
Normal file
299
macx64/include/boost/histogram/axis/variant.hpp
Normal file
@@ -0,0 +1,299 @@
|
||||
// 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)
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_VARIANT_HPP
|
||||
|
||||
#include <boost/core/typeinfo.hpp>
|
||||
#include <boost/histogram/axis/iterator.hpp>
|
||||
#include <boost/histogram/axis/polymorphic_bin.hpp>
|
||||
#include <boost/histogram/axis/traits.hpp>
|
||||
#include <boost/histogram/detail/cat.hpp>
|
||||
#include <boost/histogram/detail/meta.hpp>
|
||||
#include <boost/histogram/fwd.hpp>
|
||||
#include <boost/mp11/bind.hpp>
|
||||
#include <boost/mp11/function.hpp>
|
||||
#include <boost/mp11/list.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/variant.hpp>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace boost {
|
||||
namespace histogram {
|
||||
namespace axis {
|
||||
|
||||
template <class T, class... Us>
|
||||
T* get_if(variant<Us...>* v);
|
||||
|
||||
template <class T, class... Us>
|
||||
const T* get_if(const variant<Us...>* v);
|
||||
|
||||
/// Polymorphic axis type
|
||||
template <class... Ts>
|
||||
class variant : public iterator_mixin<variant<Ts...>> {
|
||||
using impl_type = boost::variant<Ts...>;
|
||||
using raw_types = mp11::mp_transform<detail::remove_cvref_t, impl_type>;
|
||||
|
||||
template <class T>
|
||||
using is_bounded_type = mp11::mp_contains<raw_types, detail::remove_cvref_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
using requires_bounded_type = std::enable_if_t<is_bounded_type<T>::value>;
|
||||
|
||||
// maybe metadata_type or const metadata_type, if bounded type is const
|
||||
using metadata_type = std::remove_reference_t<decltype(
|
||||
traits::metadata(std::declval<mp11::mp_first<impl_type>>()))>;
|
||||
|
||||
public:
|
||||
// cannot import ctors with using directive, it breaks gcc and msvc
|
||||
variant() = default;
|
||||
variant(const variant&) = default;
|
||||
variant& operator=(const variant&) = default;
|
||||
variant(variant&&) = default;
|
||||
variant& operator=(variant&&) = default;
|
||||
|
||||
template <typename T, typename = requires_bounded_type<T>>
|
||||
variant(T&& t) : impl(std::forward<T>(t)) {}
|
||||
|
||||
template <typename T, typename = requires_bounded_type<T>>
|
||||
variant& operator=(T&& t) {
|
||||
impl = std::forward<T>(t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
variant(const variant<Us...>& u) {
|
||||
this->operator=(u);
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
variant& operator=(const variant<Us...>& u) {
|
||||
visit(
|
||||
[this](const auto& u) {
|
||||
using U = detail::remove_cvref_t<decltype(u)>;
|
||||
detail::static_if<is_bounded_type<U>>(
|
||||
[this](const auto& u) { this->operator=(u); },
|
||||
[](const auto&) {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(U)),
|
||||
" is not convertible to a bounded type of ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(variant)))));
|
||||
},
|
||||
u);
|
||||
},
|
||||
u);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Return size of axis.
|
||||
index_type size() const {
|
||||
return visit([](const auto& x) { return x.size(); }, *this);
|
||||
}
|
||||
|
||||
/// Return options of axis or option::none_t if axis has no options.
|
||||
unsigned options() const {
|
||||
return visit([](const auto& x) { return axis::traits::options(x); }, *this);
|
||||
}
|
||||
|
||||
/// Return reference to const metadata or instance of null_type if axis has no
|
||||
/// metadata.
|
||||
const metadata_type& metadata() const {
|
||||
return visit(
|
||||
[](const auto& a) -> const metadata_type& {
|
||||
using M = decltype(traits::metadata(a));
|
||||
return detail::static_if<std::is_same<M, const metadata_type&>>(
|
||||
[](const auto& a) -> const metadata_type& { return traits::metadata(a); },
|
||||
[](const auto&) -> const metadata_type& {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
"cannot return metadata of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
|
||||
" through axis::variant interface which uses type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
|
||||
"; use boost::histogram::axis::get to obtain a reference "
|
||||
"of this axis type")));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
/// Return reference to metadata or instance of null_type if axis has no
|
||||
/// metadata.
|
||||
metadata_type& metadata() {
|
||||
return visit(
|
||||
[](auto&& a) -> metadata_type& {
|
||||
using M = decltype(traits::metadata(a));
|
||||
return detail::static_if<std::is_same<M, metadata_type&>>(
|
||||
[](auto& a) -> metadata_type& { return traits::metadata(a); },
|
||||
[](auto&) -> metadata_type& {
|
||||
BOOST_THROW_EXCEPTION(std::runtime_error(detail::cat(
|
||||
"cannot return metadata of type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(M)),
|
||||
" through axis::variant interface which uses type ",
|
||||
boost::core::demangled_name(BOOST_CORE_TYPEID(metadata_type)),
|
||||
"; use boost::histogram::axis::get to obtain a reference "
|
||||
"of this axis type")));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
/// Return index for value argument.
|
||||
/// Throws std::invalid_argument if axis has incompatible call signature.
|
||||
template <class U>
|
||||
index_type index(const U& u) const {
|
||||
return visit([&u](const auto& a) { return traits::index(a, u); }, *this);
|
||||
}
|
||||
|
||||
/// Return value for index argument.
|
||||
/// Only works for axes with value method that returns something convertible
|
||||
/// to double and will throw a runtime_error otherwise, see
|
||||
/// axis::traits::value().
|
||||
double value(real_index_type idx) const {
|
||||
return visit([idx](const auto& a) { return traits::value_as<double>(a, idx); },
|
||||
*this);
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
/// Only works for axes with value method that returns something convertible
|
||||
/// to double and will throw a runtime_error otherwise, see
|
||||
/// axis::traits::value().
|
||||
auto bin(index_type idx) const {
|
||||
return visit(
|
||||
[idx](const auto& a) {
|
||||
return detail::value_method_switch_with_return_type<double,
|
||||
polymorphic_bin<double>>(
|
||||
[idx](const auto& a) { // axis is discrete
|
||||
const auto x = a.value(idx);
|
||||
return polymorphic_bin<double>(x, x);
|
||||
},
|
||||
[idx](const auto& a) { // axis is continuous
|
||||
return polymorphic_bin<double>(a.value(idx), a.value(idx + 1));
|
||||
},
|
||||
a);
|
||||
},
|
||||
*this);
|
||||
}
|
||||
|
||||
template <class... Us>
|
||||
bool operator==(const variant<Us...>& u) const {
|
||||
return visit([&u](const auto& x) { return u == x; }, *this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const T& t) const {
|
||||
// boost::variant::operator==(T) implemented only to fail, cannot use it
|
||||
auto tp = get_if<T>(this);
|
||||
return tp && detail::relaxed_equal(*tp, t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const T& t) const {
|
||||
return !operator==(t);
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
void serialize(Archive& ar, unsigned);
|
||||
|
||||
template <class Visitor, class Variant>
|
||||
friend auto visit(Visitor&&, Variant &&)
|
||||
-> detail::visitor_return_type<Visitor, Variant>;
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T& get(variant<Us...>& v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend const T& get(const variant<Us...>& v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T&& get(variant<Us...>&& v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend T* get_if(variant<Us...>* v);
|
||||
|
||||
template <class T, class... Us>
|
||||
friend const T* get_if(const variant<Us...>* v);
|
||||
|
||||
private:
|
||||
boost::variant<Ts...> impl;
|
||||
};
|
||||
|
||||
/// Apply visitor to variant.
|
||||
template <class Visitor, class Variant>
|
||||
auto visit(Visitor&& vis, Variant&& var)
|
||||
-> detail::visitor_return_type<Visitor, Variant> {
|
||||
return boost::apply_visitor(std::forward<Visitor>(vis), var.impl);
|
||||
}
|
||||
|
||||
/// Return lvalue reference to T, throws unspecified exception if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
T& get(variant<Us...>& v) {
|
||||
return boost::get<T>(v.impl);
|
||||
}
|
||||
|
||||
/// Return rvalue reference to T, throws unspecified exception if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
T&& get(variant<Us...>&& v) {
|
||||
return boost::get<T>(std::move(v.impl));
|
||||
}
|
||||
|
||||
/// Return const reference to T, throws unspecified exception if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
const T& get(const variant<Us...>& v) {
|
||||
return boost::get<T>(v.impl);
|
||||
}
|
||||
|
||||
/// Returns pointer to T in variant or null pointer if type does not match.
|
||||
template <class T, class... Us>
|
||||
T* get_if(variant<Us...>* v) {
|
||||
return boost::relaxed_get<T>(&(v->impl));
|
||||
}
|
||||
|
||||
/// Returns pointer to const T in variant or null pointer if type does not
|
||||
/// match.
|
||||
template <class T, class... Us>
|
||||
const T* get_if(const variant<Us...>* v) {
|
||||
return boost::relaxed_get<T>(&(v->impl));
|
||||
}
|
||||
|
||||
#ifndef BOOST_HISTOGRAM_DOXYGEN_INVOKED
|
||||
// pass-through version of get for generic programming
|
||||
template <class T, class U>
|
||||
decltype(auto) get(U&& u) {
|
||||
return static_cast<detail::copy_qualifiers<U, T>>(u);
|
||||
}
|
||||
|
||||
// pass-through version of get_if for generic programming
|
||||
template <class T, class U>
|
||||
T* get_if(U* u) {
|
||||
return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<T*>(u)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
// pass-through version of get_if for generic programming
|
||||
template <class T, class U>
|
||||
const T* get_if(const U* u) {
|
||||
return std::is_same<T, detail::remove_cvref_t<U>>::value ? reinterpret_cast<const T*>(u)
|
||||
: nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace axis
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user