mirror of
https://github.com/boostorg/histogram.git
synced 2025-05-11 13:14:06 +00:00
msvc fixes, simplification and bug-fixes of mp_int, more test coverage (#159)
* fixes broken msvc build * smaller xml files for testing serialization * fixing many warnings on msvc * bug-fixes to mp_int regarding operators and new tests to check their behavior * don't expect iterable histogram::at to have size method * build benchmarks in release mode * test everything by default when b2 is run on project directory * more test coverage
This commit is contained in:
parent
9abbe46e3d
commit
2568a68f76
21
.travis.yml
21
.travis.yml
@ -36,14 +36,6 @@ matrix:
|
||||
script:
|
||||
- ../../b2 -j2 -q cxxstd=14 test examples test//serial examples//serial
|
||||
|
||||
# - name: "clang: minimal"
|
||||
# addons:
|
||||
# apt:
|
||||
# sources: ubuntu-toolchain-r-test
|
||||
# packages: libc++-dev
|
||||
# script:
|
||||
# - ./b2 -j2 -q toolset=clang cxxflags="-stdlib=libc++" linkflags="-lc++" libs/histogram
|
||||
|
||||
- name: "gcc-5: ubasan"
|
||||
addons:
|
||||
apt:
|
||||
@ -51,8 +43,10 @@ matrix:
|
||||
packages: g++-5
|
||||
script:
|
||||
# ubsan+asan disabled in serial tests, because of bug in boost/serialization
|
||||
- ../../b2 -j2 -q toolset=gcc-5 cxxstd=14 ubasan test examples &&
|
||||
../../b2 -j2 -q toolset=gcc-5 cxxstd=14 test//serial examples//serial
|
||||
- ../../b2 -j2 -q toolset=gcc-5 cxxstd=14 ubasan
|
||||
test//minimal examples//minimal &&
|
||||
../../b2 -j2 -q toolset=gcc-5 cxxstd=14
|
||||
test//serial examples//serial
|
||||
|
||||
- name: "gcc-7: coverage"
|
||||
addons:
|
||||
@ -61,7 +55,6 @@ matrix:
|
||||
packages: g++-7
|
||||
script:
|
||||
- ../../b2 -j2 -q toolset=gcc-7 coverage
|
||||
test examples test//serial examples//serial
|
||||
after_success:
|
||||
- GCOV=gcov-7 tools/cov.sh
|
||||
|
||||
@ -72,8 +65,10 @@ matrix:
|
||||
packages: g++-8
|
||||
script:
|
||||
# ubsan+asan disabled in serial tests, because of bug in boost/serialization
|
||||
- ../../b2 -j2 -q toolset=gcc-8 cxxstd=17 ubasan test examples &&
|
||||
../../b2 -j2 -q toolset=gcc-8 cxxstd=17 test//serial examples//serial
|
||||
- ../../b2 -j2 -q toolset=gcc-8 cxxstd=17 ubasan
|
||||
test//minimal examples//minimal &&
|
||||
../../b2 -j2 -q toolset=gcc-8 cxxstd=17
|
||||
test//serial examples//serial
|
||||
|
||||
before_script:
|
||||
# Cloning minimal set of Boost libraries
|
||||
|
@ -11,6 +11,7 @@ project
|
||||
: requirements
|
||||
<include>$(BOOST_ROOT)
|
||||
<include>.
|
||||
<variant>release
|
||||
;
|
||||
|
||||
alias run-speed-test :
|
||||
|
@ -51,8 +51,6 @@ double compare_1d(unsigned n, int distrib) {
|
||||
template <typename Tag, typename Storage>
|
||||
double compare_2d(unsigned n, int distrib) {
|
||||
auto r = random_array(n, distrib);
|
||||
|
||||
auto best = std::numeric_limits<double>::max();
|
||||
auto h = make_s(Tag(), Storage(), reg(100, 0, 1), reg(100, 0, 1));
|
||||
auto t = clock();
|
||||
for (auto it = r.get(), end = r.get() + n; it != end;) {
|
||||
|
@ -4,37 +4,42 @@
|
||||
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
run getting_started_listing_01.cpp ;
|
||||
run getting_started_listing_02.cpp ;
|
||||
run getting_started_listing_03.cpp ;
|
||||
run guide_axis_basic_demo.cpp ;
|
||||
run guide_axis_circular.cpp ;
|
||||
run guide_axis_growing.cpp ;
|
||||
run guide_axis_with_labels.cpp ;
|
||||
run guide_axis_with_transform.cpp ;
|
||||
run guide_axis_with_uoflow_off.cpp ;
|
||||
run guide_custom_2d_axis.cpp ;
|
||||
run guide_custom_accumulators.cpp ;
|
||||
run guide_custom_minimal_axis.cpp ;
|
||||
run guide_custom_modified_axis.cpp ;
|
||||
run guide_custom_storage.cpp ;
|
||||
run guide_fill_accumulator.cpp ;
|
||||
run guide_fill_histogram.cpp ;
|
||||
run guide_fill_profile.cpp ;
|
||||
run guide_histogram_operators.cpp ;
|
||||
run guide_histogram_reduction.cpp ;
|
||||
run guide_histogram_streaming.cpp ;
|
||||
run guide_indexed_access.cpp ;
|
||||
run guide_make_dynamic_histogram.cpp ;
|
||||
run guide_make_static_histogram.cpp ;
|
||||
run guide_parallel_filling.cpp ;
|
||||
run guide_stdlib_algorithms.cpp ;
|
||||
test-suite minimal :
|
||||
[ run getting_started_listing_01.cpp ]
|
||||
[ run getting_started_listing_02.cpp ]
|
||||
[ run getting_started_listing_03.cpp ]
|
||||
[ run guide_axis_basic_demo.cpp ]
|
||||
[ run guide_axis_circular.cpp ]
|
||||
[ run guide_axis_growing.cpp ]
|
||||
[ run guide_axis_with_labels.cpp ]
|
||||
[ run guide_axis_with_transform.cpp ]
|
||||
[ run guide_axis_with_uoflow_off.cpp ]
|
||||
[ run guide_custom_2d_axis.cpp ]
|
||||
[ run guide_custom_accumulators.cpp ]
|
||||
[ run guide_custom_minimal_axis.cpp ]
|
||||
[ run guide_custom_modified_axis.cpp ]
|
||||
[ run guide_custom_storage.cpp ]
|
||||
[ run guide_fill_accumulator.cpp ]
|
||||
[ run guide_fill_histogram.cpp ]
|
||||
[ run guide_fill_profile.cpp ]
|
||||
[ run guide_histogram_operators.cpp ]
|
||||
[ run guide_histogram_reduction.cpp ]
|
||||
[ run guide_histogram_streaming.cpp ]
|
||||
[ run guide_indexed_access.cpp ]
|
||||
[ run guide_make_dynamic_histogram.cpp ]
|
||||
[ run guide_make_static_histogram.cpp ]
|
||||
[ run guide_parallel_filling.cpp ]
|
||||
[ run guide_stdlib_algorithms.cpp ]
|
||||
;
|
||||
|
||||
alias libserial : /boost/serialization//boost_serialization : <link>static ;
|
||||
|
||||
alias serial :
|
||||
test-suite serial :
|
||||
[ run guide_histogram_serialization.cpp libserial ]
|
||||
;
|
||||
|
||||
test-suite all : minimal serial ;
|
||||
|
||||
explicit minimal ;
|
||||
explicit libserial ;
|
||||
explicit serial ;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
#define BOOST_HISTOGRAM_AXIS_OPTION_HPP
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
@ -44,26 +45,28 @@ using growth = bit<3>;
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr inline unsigned join_impl(unsigned a) { return a; }
|
||||
|
||||
template <unsigned N, class... Ts>
|
||||
constexpr unsigned join_impl(unsigned a, axis::option::bit<N>, Ts... ts) {
|
||||
using namespace axis::option;
|
||||
const auto o = bit<N>::value;
|
||||
const auto c = a | o;
|
||||
if (o == underflow::value) return join_impl(c & ~circular::value, ts...);
|
||||
if (o == circular::value)
|
||||
return join_impl(c & ~(underflow::value | growth::value), ts...);
|
||||
if (o == growth::value) return join_impl(c & ~circular::value, ts...);
|
||||
return join_impl(c, ts...);
|
||||
}
|
||||
template <class T, class U>
|
||||
struct join_impl : axis::option_set<(T::value | U::value)> {};
|
||||
template <class T>
|
||||
struct join_impl<T, axis::option::underflow>
|
||||
: axis::option_set<((T::value & ~axis::option::circular::value) |
|
||||
axis::option::underflow::value)> {};
|
||||
template <class T>
|
||||
struct join_impl<T, axis::option::circular>
|
||||
: axis::option_set<(
|
||||
(T::value & ~(axis::option::growth::value | axis::option::underflow::value)) |
|
||||
axis::option::circular::value)> {};
|
||||
template <class T>
|
||||
struct join_impl<T, axis::option::growth>
|
||||
: axis::option_set<((T::value & ~axis::option::circular::value) |
|
||||
axis::option::growth::value)> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
namespace axis {
|
||||
/// Combines options and corrects for mutually exclusive options.
|
||||
template <class T, class... Ts>
|
||||
using join = axis::option_set<detail::join_impl(T::value, Ts{}...)>;
|
||||
template <class... Ts>
|
||||
using join = mp11::mp_fold<mp11::mp_list<Ts...>, option_set<0>, detail::join_impl>;
|
||||
|
||||
/// Test whether the bits in b are also set in a.
|
||||
template <class T, class U>
|
||||
|
@ -286,7 +286,7 @@ public:
|
||||
else {
|
||||
z = std::numeric_limits<internal_value_type>::infinity() * delta_;
|
||||
}
|
||||
return this->inverse(z) * unit_type();
|
||||
return static_cast<value_type>(this->inverse(z) * unit_type());
|
||||
}
|
||||
|
||||
/// Return bin for index argument.
|
||||
|
@ -73,9 +73,9 @@ decltype(auto) metadata(T&& t) noexcept {
|
||||
|
||||
template <class T>
|
||||
using static_options =
|
||||
detail::mp_eval_or<detail::static_options_impl, detail::remove_cvref_t<T>,
|
||||
mp11::mp_if<detail::has_method_update<detail::remove_cvref_t<T>>,
|
||||
axis::option::growth, axis::option::none>>;
|
||||
detail::mp_eval_or<mp11::mp_if<detail::has_method_update<detail::remove_cvref_t<T>>,
|
||||
axis::option::growth, axis::option::none>,
|
||||
detail::static_options_impl, detail::remove_cvref_t<T>>;
|
||||
|
||||
template <class T>
|
||||
constexpr unsigned options(const T& t) noexcept {
|
||||
@ -112,7 +112,11 @@ template <class T, class U>
|
||||
auto index(const T& axis, const U& value) {
|
||||
using V = detail::arg_type<decltype(&T::index)>;
|
||||
return detail::static_if<std::is_convertible<U, V>>(
|
||||
[&value](const auto& axis) { return axis.index(value); },
|
||||
[&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 T&) {
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument(
|
||||
detail::cat(boost::core::demangled_name(BOOST_CORE_TYPEID(T)),
|
||||
|
@ -112,14 +112,14 @@ void linearize_index(optional_index& out, const A& axis, const axis::index_type
|
||||
template <class S, class A, class T>
|
||||
void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
bool update_needed = false;
|
||||
auto sh = shifts;
|
||||
for_each_axis(axes, [&](const auto&) { update_needed |= (*sh++ != 0); });
|
||||
auto sit = shifts;
|
||||
for_each_axis(axes, [&](const auto&) { update_needed |= (*sit++ != 0); });
|
||||
if (!update_needed) return;
|
||||
struct item {
|
||||
axis::index_type idx, old_extend;
|
||||
std::size_t new_stride;
|
||||
} data[buffer_size<A>::value];
|
||||
auto sit = shifts;
|
||||
sit = shifts;
|
||||
auto dit = data;
|
||||
std::size_t s = 1;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
@ -129,15 +129,17 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
});
|
||||
auto new_storage = make_default(storage);
|
||||
new_storage.reset(detail::bincount(axes));
|
||||
const auto dlast = data + get_size(axes) - 1;
|
||||
for (const auto& x : storage) {
|
||||
auto ns = new_storage.begin();
|
||||
sit = shifts;
|
||||
dit = data;
|
||||
for_each_axis(axes, [&](const auto& a) {
|
||||
using opt = axis::traits::static_options<remove_cvref_t<decltype(a)>>;
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
if (axis::test<opt, axis::option::underflow>::value) {
|
||||
if (dit->idx == 0) {
|
||||
// noop
|
||||
// axis has underflow and we are in the underflow bin:
|
||||
// keep storage pointer unchanged
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
@ -145,20 +147,26 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
}
|
||||
if (axis::test<opt, axis::option::overflow>::value) {
|
||||
if (dit->idx == dit->old_extend - 1) {
|
||||
// axis has overflow and we are in the overflow bin:
|
||||
// move storage pointer to corresponding overflow bin position
|
||||
ns += (axis::traits::extend(a) - 1) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// we are in a normal bin:
|
||||
// move storage pointer to index position, apply positive shifts
|
||||
ns += (dit->idx + std::max(*sit, 0)) * dit->new_stride;
|
||||
++dit;
|
||||
++sit;
|
||||
});
|
||||
// assign old value to new location
|
||||
*ns = x;
|
||||
// advance multi-dimensional index
|
||||
dit = data;
|
||||
++dit->idx;
|
||||
while (dit != (data + get_size(axes) - 1) && dit->idx == dit->old_extend) {
|
||||
while (dit != dlast && dit->idx == dit->old_extend) {
|
||||
dit->idx = 0;
|
||||
++(++dit)->idx;
|
||||
}
|
||||
@ -166,12 +174,6 @@ void maybe_replace_storage(S& storage, const A& axes, const T& shifts) {
|
||||
storage = std::move(new_storage);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct size_or_zero : mp11::mp_size_t<0> {};
|
||||
|
||||
template <class... Ts>
|
||||
struct size_or_zero<std::tuple<Ts...>> : mp11::mp_size_t<sizeof...(Ts)> {};
|
||||
|
||||
// special case: if histogram::operator()(tuple(1, 2)) is called on 1d histogram
|
||||
// with axis that accepts 2d tuple, this should not fail
|
||||
// - solution is to forward tuples of size > 1 directly to axis for 1d
|
||||
@ -192,8 +194,8 @@ optional_index args_to_index(std::false_type, S&, const T& axes, const U& args)
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = size_or_zero<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(M == 0 ? N : M)>>([&](auto J) {
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
@ -212,8 +214,8 @@ optional_index args_to_index(std::true_type, S& storage, T& axes, const U& args)
|
||||
if (rank != N)
|
||||
BOOST_THROW_EXCEPTION(
|
||||
std::invalid_argument("number of arguments != histogram rank"));
|
||||
constexpr unsigned M = size_or_zero<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(M == 0 ? N : M)>>([&](auto J) {
|
||||
constexpr unsigned M = buffer_size<remove_cvref_t<decltype(axes)>>::value;
|
||||
mp11::mp_for_each<mp11::mp_iota_c<(N < M ? N : M)>>([&](auto J) {
|
||||
linearize_value(idx, shifts[J], axis_get<J>(axes), std::get<(J + I)>(args));
|
||||
});
|
||||
}
|
||||
@ -334,7 +336,7 @@ optional_index at(const A& axes, const std::tuple<Us...>& args) {
|
||||
|
||||
template <typename A, typename U>
|
||||
optional_index at(const A& axes, const U& args) {
|
||||
if (get_size(axes) != args.size())
|
||||
if (get_size(axes) != get_size(args))
|
||||
BOOST_THROW_EXCEPTION(std::invalid_argument("number of arguments != histogram rank"));
|
||||
optional_index idx;
|
||||
using std::begin;
|
||||
|
@ -52,8 +52,9 @@ using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
template <class T, class U>
|
||||
using convert_integer = mp11::mp_if<std::is_integral<remove_cvref_t<T>>, U, T>;
|
||||
|
||||
template <template <class> class F, class T, class E>
|
||||
using mp_eval_or = mp11::mp_eval_if_c<!(mp11::mp_valid<F, T>::value), E, F, T>;
|
||||
// to be replaced by official version from mp11
|
||||
template <class E, template <class...> class F, class... Ts>
|
||||
using mp_eval_or = mp11::mp_eval_if_c<!(mp11::mp_valid<F, Ts...>::value), E, F, Ts...>;
|
||||
|
||||
template <class T1, class T2>
|
||||
using copy_qualifiers = mp11::mp_if<
|
||||
@ -171,7 +172,7 @@ using get_value_method_return_type_impl = decltype(std::declval<T&>().value(0));
|
||||
|
||||
template <typename T, typename R>
|
||||
using has_method_value_with_convertible_return_type =
|
||||
typename std::is_convertible<mp_eval_or<get_value_method_return_type_impl, T, void>,
|
||||
typename std::is_convertible<mp_eval_or<void, get_value_method_return_type_impl, T>,
|
||||
R>::type;
|
||||
|
||||
BOOST_HISTOGRAM_DETECT(has_method_options, (&T::options));
|
||||
@ -328,7 +329,9 @@ std::size_t get_size_impl(std::true_type, const T&) noexcept {
|
||||
|
||||
template <class T>
|
||||
std::size_t get_size_impl(std::false_type, const T& t) noexcept {
|
||||
return t.size();
|
||||
using std::begin;
|
||||
using std::end;
|
||||
return static_cast<std::size_t>(std::distance(begin(t), end(t)));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -338,8 +341,8 @@ std::size_t get_size(const T& t) noexcept {
|
||||
|
||||
template <class T>
|
||||
using buffer_size =
|
||||
mp_eval_or<tuple_size_t, T,
|
||||
std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>>;
|
||||
mp_eval_or<std::integral_constant<std::size_t, BOOST_HISTOGRAM_DETAIL_AXES_LIMIT>,
|
||||
tuple_size_t, T>;
|
||||
|
||||
template <class T, std::size_t N>
|
||||
class sub_array : public std::array<T, N> {
|
||||
@ -376,7 +379,7 @@ template <class T>
|
||||
using get_scale_type_helper = typename T::value_type;
|
||||
|
||||
template <class T>
|
||||
using get_scale_type = detail::mp_eval_or<detail::get_scale_type_helper, T, T>;
|
||||
using get_scale_type = mp_eval_or<T, detail::get_scale_type_helper, T>;
|
||||
|
||||
struct one_unit {};
|
||||
|
||||
@ -394,7 +397,7 @@ template <class T>
|
||||
using get_unit_type_helper = typename T::unit_type;
|
||||
|
||||
template <class T>
|
||||
using get_unit_type = detail::mp_eval_or<detail::get_unit_type_helper, T, one_unit>;
|
||||
using get_unit_type = mp_eval_or<one_unit, detail::get_unit_type_helper, T>;
|
||||
|
||||
template <class T, class R = get_scale_type<T>>
|
||||
R get_scale(const T& t) {
|
||||
@ -404,6 +407,13 @@ R get_scale(const T& t) {
|
||||
template <class T, class Default>
|
||||
using replace_default = mp11::mp_if<std::is_same<T, use_default>, Default, T>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible_helper =
|
||||
mp11::mp_apply<mp11::mp_all, mp11::mp_transform<std::is_convertible, T, U>>;
|
||||
|
||||
template <class T, class U>
|
||||
using is_convertible = mp_eval_or<std::false_type, is_convertible_helper, T, U>;
|
||||
|
||||
} // namespace detail
|
||||
} // namespace histogram
|
||||
} // namespace boost
|
||||
|
@ -154,7 +154,7 @@ public:
|
||||
*/
|
||||
template <class... Ts>
|
||||
auto operator()(const Ts&... ts) {
|
||||
return operator()(std::forward_as_tuple(ts...));
|
||||
return operator()(std::make_tuple(ts...));
|
||||
}
|
||||
|
||||
/// Fill histogram with values, an optional weight, and/or a sample from a `std::tuple`.
|
||||
|
@ -160,20 +160,23 @@ public:
|
||||
const auto clast = ca + hist_.rank() - 1;
|
||||
std::size_t stride = 1;
|
||||
h.for_each_axis([&, this](const auto& a) {
|
||||
using opt = axis::traits::static_options<detail::remove_cvref_t<decltype(a)>>;
|
||||
const auto shift = axis::test<opt, axis::option::underflow>::value;
|
||||
using opt = axis::traits::static_options<decltype(a)>;
|
||||
constexpr auto under = axis::test<opt, axis::option::underflow>::value ? 1 : 0;
|
||||
constexpr auto over = axis::test<opt, axis::option::overflow>::value ? 1 : 0;
|
||||
const auto size = a.size();
|
||||
|
||||
ca->extend = axis::traits::extend(a);
|
||||
ca->begin = cover_all_ ? -shift : 0;
|
||||
ca->end = ca->extend - shift -
|
||||
(cover_all_ ? 0 : axis::test<opt, axis::option::overflow>::value);
|
||||
ca->extend = size + under + over;
|
||||
// -1 if underflow and cover all, else 0
|
||||
ca->begin = cover_all_ ? -under : 0;
|
||||
// size + 1 if overflow and cover all, else size
|
||||
ca->end = cover_all_ ? size + over : size;
|
||||
ca->idx = ca->begin;
|
||||
|
||||
begin_ += (ca->begin + shift) * stride;
|
||||
begin_ += (ca->begin + under) * stride;
|
||||
if (ca < clast)
|
||||
end_ += (ca->begin + shift) * stride;
|
||||
end_ += (ca->begin + under) * stride;
|
||||
else
|
||||
end_ += (ca->end + shift) * stride;
|
||||
end_ += (ca->end + under) * stride;
|
||||
|
||||
stride *= ca->extend;
|
||||
++ca;
|
||||
|
@ -179,7 +179,7 @@ template <class A>
|
||||
template <class Archive>
|
||||
void unlimited_storage<A>::serialize(Archive& ar, unsigned /* version */) {
|
||||
if (Archive::is_loading::value) {
|
||||
buffer_type dummy(0, buffer.alloc);
|
||||
buffer_type dummy(buffer.alloc);
|
||||
std::size_t size;
|
||||
ar& serialization::make_nvp("type", dummy.type);
|
||||
ar& serialization::make_nvp("size", size);
|
||||
|
@ -43,7 +43,9 @@ bool safe_increment(T& t) {
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool safe_radd(std::true_type, T& t, const U& u) {
|
||||
bool safe_radd(T& t, const U& u) {
|
||||
static_assert(is_unsigned_integral<T>::value, "T must be unsigned integral type");
|
||||
static_assert(is_unsigned_integral<U>::value, "T must be unsigned integral type");
|
||||
if (static_cast<T>(std::numeric_limits<T>::max() - t) >= u) {
|
||||
t += static_cast<T>(u); // static_cast to suppress conversion warning
|
||||
return true;
|
||||
@ -51,45 +53,6 @@ bool safe_radd(std::true_type, T& t, const U& u) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool safe_radd(std::false_type, T& t, const U& u) {
|
||||
static_assert(std::is_integral<U>::value, "U must be integral type");
|
||||
if (u >= 0) {
|
||||
if (static_cast<T>(std::numeric_limits<T>::max() - t) >=
|
||||
static_cast<std::make_unsigned_t<U>>(u)) {
|
||||
t += static_cast<T>(u);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (t >= static_cast<std::make_unsigned_t<U>>(-u)) {
|
||||
t -= static_cast<T>(-u);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, class A>
|
||||
bool safe_radd(std::false_type, T& t, const mp_int<A>& u) {
|
||||
if (u >= 0) {
|
||||
if (std::numeric_limits<T>::max() - t > u) {
|
||||
t += static_cast<T>(u);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (u + t >= 0) {
|
||||
t -= static_cast<T>(-u);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
bool safe_radd(T& t, const U& u) {
|
||||
static_assert(is_unsigned_integral<T>::value, "T must be unsigned integral type");
|
||||
return safe_radd(is_unsigned_integral<U>{}, t, u);
|
||||
}
|
||||
|
||||
// use boost.multiprecision.cpp_int in your own code, it is much more sophisticated
|
||||
// than this implementation; we use it here to reduce coupling between boost libs
|
||||
template <class Allocator>
|
||||
@ -107,7 +70,7 @@ struct mp_int {
|
||||
}
|
||||
|
||||
mp_int& operator++() {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
std::size_t i = 0;
|
||||
while (!safe_increment(data[i])) {
|
||||
data[i] = 0;
|
||||
@ -153,7 +116,7 @@ struct mp_int {
|
||||
}
|
||||
|
||||
mp_int& operator+=(uint64_t o) {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
if (safe_radd(data[0], o)) return *this;
|
||||
add_remainder(data[0], o);
|
||||
// carry the one, data may grow several times
|
||||
@ -168,40 +131,45 @@ struct mp_int {
|
||||
}
|
||||
|
||||
operator double() const noexcept {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
double result = data[0];
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
double result = static_cast<double>(data[0]);
|
||||
std::size_t i = 0;
|
||||
while (++i < data.size())
|
||||
result += static_cast<double>(data[i]) * std::pow(2.0, i * 64);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool operator<(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
bool less(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
return data.size() == 1 && data[0] < o;
|
||||
}
|
||||
|
||||
bool operator>(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
bool greater(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
return data.size() > 1 || data[0] > o;
|
||||
}
|
||||
|
||||
bool operator==(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() >= 1);
|
||||
bool equal(uint64_t o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
return data.size() == 1 && data[0] == o;
|
||||
}
|
||||
|
||||
bool operator<(double o) const noexcept { return operator double() < o; }
|
||||
bool less(double o) const noexcept { return operator double() < o; }
|
||||
|
||||
bool operator>(double o) const noexcept { return operator double() > o; }
|
||||
bool greater(double o) const noexcept { return operator double() > o; }
|
||||
|
||||
bool operator==(double o) const noexcept { return operator double() == o; }
|
||||
bool equal(double o) const noexcept { return operator double() == o; }
|
||||
|
||||
bool operator<(const mp_int& o) const noexcept {
|
||||
bool less(const mp_int& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(o.data.size() > 0u);
|
||||
// no leading zeros allowed
|
||||
BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
|
||||
BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
|
||||
if (data.size() < o.data.size()) return true;
|
||||
if (data.size() > o.data.size()) return false;
|
||||
auto s = data.size();
|
||||
while (s > 0) {
|
||||
while (s > 0u) {
|
||||
--s;
|
||||
if (data[s] < o.data[s]) return true;
|
||||
if (data[s] > o.data[s]) return false;
|
||||
@ -209,11 +177,16 @@ struct mp_int {
|
||||
return false; // args are equal
|
||||
}
|
||||
|
||||
bool operator>(const mp_int& o) const noexcept {
|
||||
bool greater(const mp_int& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(o.data.size() > 0u);
|
||||
// no leading zeros allowed
|
||||
BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
|
||||
BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
|
||||
if (data.size() > o.data.size()) return true;
|
||||
if (data.size() < o.data.size()) return false;
|
||||
auto s = data.size();
|
||||
while (s > 0) {
|
||||
while (s > 0u) {
|
||||
--s;
|
||||
if (data[s] > o.data[s]) return true;
|
||||
if (data[s] < o.data[s]) return false;
|
||||
@ -221,7 +194,12 @@ struct mp_int {
|
||||
return false; // args are equal
|
||||
}
|
||||
|
||||
bool operator==(const mp_int& o) const noexcept {
|
||||
bool equal(const mp_int& o) const noexcept {
|
||||
BOOST_ASSERT(data.size() > 0u);
|
||||
BOOST_ASSERT(o.data.size() > 0u);
|
||||
// no leading zeros allowed
|
||||
BOOST_ASSERT(data.size() == 1 || data.back() > 0u);
|
||||
BOOST_ASSERT(o.data.size() == 1 || o.data.back() > 0u);
|
||||
if (data.size() != o.data.size()) return false;
|
||||
for (std::size_t s = 0; s < data.size(); ++s)
|
||||
if (data[s] != o.data[s]) return false;
|
||||
@ -229,66 +207,86 @@ struct mp_int {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator<(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? operator<(static_cast<uint64_t>(o)) :
|
||||
operator<(static_cast<double>(o));
|
||||
bool less(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? less(static_cast<uint64_t>(o))
|
||||
: less(static_cast<double>(o));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator>(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? operator>(static_cast<uint64_t>(o)) :
|
||||
operator>(static_cast<double>(o));
|
||||
bool greater(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? greater(static_cast<uint64_t>(o))
|
||||
: greater(static_cast<double>(o));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator==(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? operator==(static_cast<uint64_t>(o)) :
|
||||
operator==(static_cast<double>(o));
|
||||
bool equal(const T& o) const noexcept {
|
||||
return std::is_integral<T>::value ? equal(static_cast<uint64_t>(o))
|
||||
: equal(static_cast<double>(o));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator<=(const T& o) const noexcept {
|
||||
return !operator>(o);
|
||||
friend bool operator<(const mp_int& a, const T& o) noexcept {
|
||||
return a.less(o);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator>=(const T& o) const noexcept {
|
||||
return !operator<(o);
|
||||
friend bool operator>(const mp_int& a, const T& o) noexcept {
|
||||
return a.greater(o);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool operator!=(const T& o) const noexcept {
|
||||
return !operator==(o);
|
||||
friend bool operator==(const mp_int& a, const T& o) noexcept {
|
||||
return a.equal(o);
|
||||
}
|
||||
template <class T>
|
||||
friend bool operator<=(const mp_int& a, const T& o) noexcept {
|
||||
return !a.greater(o);
|
||||
}
|
||||
template <class T>
|
||||
friend bool operator>=(const mp_int& a, const T& o) noexcept {
|
||||
return !a.less(o);
|
||||
}
|
||||
template <class T>
|
||||
friend bool operator!=(const mp_int& a, const T& o) noexcept {
|
||||
return !a.equal(o);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator<(const T& a, const mp_int& b) noexcept {
|
||||
return !(b >= a);
|
||||
// a < b == b >= a == !(b < a)
|
||||
return !b.less(a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator>(const T& a, const mp_int& b) noexcept {
|
||||
return !(b <= a);
|
||||
// a > b == b <= a == !(b > a)
|
||||
return !b.greater(a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator<=(const T& a, const mp_int& b) noexcept {
|
||||
return !(b > a);
|
||||
return b.greater(a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator>=(const T& a, const mp_int& b) noexcept {
|
||||
return !(b < a);
|
||||
return b.less(a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator==(const T& a, const mp_int& b) noexcept {
|
||||
return b == a;
|
||||
return b.equal(a);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
friend bool operator!=(const T& a, const mp_int& b) noexcept {
|
||||
return b != a;
|
||||
return !b.equal(a);
|
||||
}
|
||||
|
||||
friend bool operator<(const mp_int& a, const mp_int& b) noexcept { return a.less(b); }
|
||||
friend bool operator>(const mp_int& a, const mp_int& b) noexcept {
|
||||
return a.greater(b);
|
||||
}
|
||||
friend bool operator<=(const mp_int& a, const mp_int& b) noexcept {
|
||||
return b.greater(a);
|
||||
}
|
||||
friend bool operator>=(const mp_int& a, const mp_int& b) noexcept { return b.less(a); }
|
||||
friend bool operator==(const mp_int& a, const mp_int& b) noexcept { return a.equal(b); }
|
||||
friend bool operator!=(const mp_int& a, const mp_int& b) noexcept {
|
||||
return !a.equal(b);
|
||||
}
|
||||
|
||||
uint64_t& maybe_extend(std::size_t i) {
|
||||
@ -297,7 +295,7 @@ struct mp_int {
|
||||
}
|
||||
|
||||
static void add_remainder(uint64_t& d, const uint64_t o) noexcept {
|
||||
BOOST_ASSERT(d > 0);
|
||||
BOOST_ASSERT(d > 0u);
|
||||
// in decimal system it would look like this:
|
||||
// 8 + 8 = 6 = 8 - (9 - 8) - 1
|
||||
// 9 + 1 = 0 = 9 - (9 - 1) - 1
|
||||
@ -331,7 +329,7 @@ auto create_buffer(Allocator& a, std::size_t n) {
|
||||
|
||||
template <class Allocator, class Iterator>
|
||||
auto create_buffer(Allocator& a, std::size_t n, Iterator iter) {
|
||||
BOOST_ASSERT(n > 0);
|
||||
BOOST_ASSERT(n > 0u);
|
||||
using AT = std::allocator_traits<Allocator>;
|
||||
auto ptr = AT::allocate(a, n); // may throw
|
||||
static_assert(std::is_trivially_copyable<decltype(ptr)>::value,
|
||||
@ -354,7 +352,7 @@ template <class Allocator>
|
||||
void destroy_buffer(Allocator& a, typename std::allocator_traits<Allocator>::pointer p,
|
||||
std::size_t n) {
|
||||
BOOST_ASSERT(p);
|
||||
BOOST_ASSERT(n > 0);
|
||||
BOOST_ASSERT(n > 0u);
|
||||
using AT = std::allocator_traits<Allocator>;
|
||||
auto it = p + n;
|
||||
while (it != p) AT::destroy(a, --it);
|
||||
@ -421,21 +419,7 @@ private:
|
||||
return f(static_cast<double*>(ptr), std::forward<Ts>(ts)...);
|
||||
}
|
||||
|
||||
buffer_type(std::size_t s = 0, allocator_type a = {})
|
||||
: alloc(std::move(a)), size(s), type(type_index<uint8_t>()) {
|
||||
if (size > 0) {
|
||||
// rebind allocator
|
||||
using alloc_type = typename std::allocator_traits<
|
||||
allocator_type>::template rebind_alloc<uint8_t>;
|
||||
alloc_type a(alloc);
|
||||
try {
|
||||
ptr = detail::create_buffer(a, size); // may throw
|
||||
} catch (...) {
|
||||
size = 0;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer_type(allocator_type a = {}) : alloc(std::move(a)) {}
|
||||
|
||||
buffer_type(buffer_type&& o) noexcept
|
||||
: alloc(std::move(o.alloc)), size(o.size), type(o.type), ptr(o.ptr) {
|
||||
@ -626,9 +610,7 @@ public:
|
||||
|
||||
template <class T>
|
||||
reference& operator-=(const T& t) {
|
||||
base_type::buffer_->apply(adder(), *base_type::buffer_, base_type::idx_,
|
||||
-static_cast<double>(t));
|
||||
return *this;
|
||||
return operator+=(-t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -684,7 +666,7 @@ public:
|
||||
using const_iterator = iterator_t<const value_type, const_reference, const buffer_type>;
|
||||
using iterator = iterator_t<value_type, reference, buffer_type>;
|
||||
|
||||
explicit unlimited_storage(allocator_type a = {}) : buffer(0, std::move(a)) {}
|
||||
explicit unlimited_storage(allocator_type a = {}) : buffer(std::move(a)) {}
|
||||
unlimited_storage(const unlimited_storage&) = default;
|
||||
unlimited_storage& operator=(const unlimited_storage&) = default;
|
||||
unlimited_storage(unlimited_storage&&) = default;
|
||||
@ -746,7 +728,7 @@ public:
|
||||
/// @private used by unit tests, not part of generic storage interface
|
||||
template <class T>
|
||||
unlimited_storage(std::size_t s, const T* p, allocator_type a = {})
|
||||
: buffer(0, std::move(a)) {
|
||||
: buffer(std::move(a)) {
|
||||
buffer.template make<T>(s, p);
|
||||
}
|
||||
|
||||
@ -777,37 +759,49 @@ private:
|
||||
|
||||
struct adder {
|
||||
template <class Buffer, class U>
|
||||
void if_U_is_integral(std::true_type, mp_int* tp, Buffer&, std::size_t i,
|
||||
const U& x) {
|
||||
tp[i] += x;
|
||||
void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
|
||||
tp[i] += static_cast<double>(x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void if_U_is_integral(std::true_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
if (detail::safe_radd(tp[i], x)) return;
|
||||
if (x >= 0) {
|
||||
using V = mp11::mp_at_c<types, (type_index<T>() + 1)>;
|
||||
b.template make<V>(b.size, tp);
|
||||
if_U_is_integral(std::true_type{}, static_cast<V*>(b.ptr), b, i, x);
|
||||
} else {
|
||||
if_U_is_integral(std::false_type{}, tp, b, i, x);
|
||||
}
|
||||
void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
U_is_integral(std::is_integral<U>{}, tp, b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void if_U_is_integral(std::false_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
void U_is_integral(std::false_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
b.template make<double>(b.size, tp);
|
||||
operator()(static_cast<double*>(b.ptr), b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void operator()(T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
if_U_is_integral(std::is_integral<U>{}, tp, b, i, x);
|
||||
void U_is_integral(std::true_type, T* tp, Buffer& b, std::size_t i, const U& x) {
|
||||
U_is_unsigned_integral(std::is_unsigned<U>{}, tp, b, i, x);
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_unsigned_integral(std::false_type, T* tp, Buffer& b, std::size_t i,
|
||||
const U& x) {
|
||||
if (x >= 0)
|
||||
U_is_unsigned_integral(std::true_type{}, tp, b, i,
|
||||
static_cast<typename std::make_unsigned<U>::type>(x));
|
||||
else
|
||||
U_is_integral(std::false_type{}, tp, b, i, static_cast<double>(x));
|
||||
}
|
||||
|
||||
template <class Buffer, class U>
|
||||
void operator()(double* tp, Buffer&, std::size_t i, const U& x) {
|
||||
tp[i] += static_cast<double>(x);
|
||||
void U_is_unsigned_integral(std::true_type, mp_int* tp, Buffer&, std::size_t i,
|
||||
const U& x) {
|
||||
tp[i] += x;
|
||||
}
|
||||
|
||||
template <class T, class Buffer, class U>
|
||||
void U_is_unsigned_integral(std::true_type, T* tp, Buffer& b, std::size_t i,
|
||||
const U& x) {
|
||||
if (detail::safe_radd(tp[i], x)) return;
|
||||
using V = mp11::mp_at_c<types, (type_index<T>() + 1)>;
|
||||
b.template make<V>(b.size, tp);
|
||||
U_is_unsigned_integral(std::true_type{}, static_cast<V*>(b.ptr), b, i, x);
|
||||
}
|
||||
};
|
||||
|
||||
|
63
test/Jamfile
63
test/Jamfile
@ -14,47 +14,52 @@ project
|
||||
<define>XML_PATH=\\\"$(THIS_PATH)/\\\"
|
||||
;
|
||||
|
||||
run algorithm_project_test.cpp ;
|
||||
run algorithm_reduce_test.cpp ;
|
||||
run algorithm_sum_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 ;
|
||||
run boost_range_support_test.cpp ;
|
||||
run boost_units_support_test.cpp ;
|
||||
run detail_test.cpp ;
|
||||
run histogram_dynamic_test.cpp ;
|
||||
run histogram_growing_test.cpp ;
|
||||
run histogram_mixed_test.cpp ;
|
||||
run histogram_operators_test.cpp ;
|
||||
run histogram_test.cpp ;
|
||||
run indexed_test.cpp ;
|
||||
run internal_accumulators_test.cpp ;
|
||||
run linearize_test.cpp ;
|
||||
run meta_test.cpp ;
|
||||
run storage_adaptor_test.cpp ;
|
||||
run unlimited_storage_test.cpp ;
|
||||
run utility_test.cpp ;
|
||||
test-suite minimal :
|
||||
[ run algorithm_project_test.cpp ]
|
||||
[ run algorithm_reduce_test.cpp ]
|
||||
[ run algorithm_sum_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 ]
|
||||
[ run boost_range_support_test.cpp ]
|
||||
[ run boost_units_support_test.cpp ]
|
||||
[ run detail_test.cpp ]
|
||||
[ run histogram_dynamic_test.cpp ]
|
||||
[ run histogram_growing_test.cpp ]
|
||||
[ run histogram_mixed_test.cpp ]
|
||||
[ run histogram_operators_test.cpp ]
|
||||
[ run histogram_test.cpp ]
|
||||
[ run indexed_test.cpp ]
|
||||
[ run internal_accumulators_test.cpp ]
|
||||
[ run linearize_test.cpp ]
|
||||
[ run meta_test.cpp ]
|
||||
[ run storage_adaptor_test.cpp ]
|
||||
[ run unlimited_storage_test.cpp ]
|
||||
[ run utility_test.cpp ]
|
||||
;
|
||||
|
||||
# has additional requirements only available on develop branch
|
||||
alias deduction_guides : [ run deduction_guides_test.cpp ] ;
|
||||
test-suite deduction_guides : [ run deduction_guides_test.cpp ] ;
|
||||
|
||||
# disabled until boost.parameter usage is fixed
|
||||
alias accumulator : [ run boost_accumulators_support_test.cpp ] ;
|
||||
test-suite accumulator : [ run boost_accumulators_support_test.cpp ] ;
|
||||
|
||||
alias libserial : /boost/serialization//boost_serialization : <link>static ;
|
||||
|
||||
alias serial :
|
||||
test-suite serial :
|
||||
[ run storage_adaptor_serialization_test.cpp libserial ]
|
||||
[ run histogram_serialization_test.cpp libserial ]
|
||||
[ run unlimited_storage_serialization_test.cpp libserial ]
|
||||
;
|
||||
|
||||
test-suite all : minimal serial ;
|
||||
|
||||
explicit minimal ;
|
||||
explicit libserial ;
|
||||
explicit serial ;
|
||||
explicit accumulator ;
|
||||
|
@ -13,31 +13,40 @@
|
||||
|
||||
using namespace boost::histogram;
|
||||
|
||||
using regular =
|
||||
axis::regular<double, axis::transform::id, axis::null_type, axis::option::growth>;
|
||||
using def = use_default;
|
||||
|
||||
// using integer = axis::integer<double, axis::null_type,
|
||||
// axis::option::underflow |
|
||||
// axis::option::overflow
|
||||
// | axis::option::growth>;
|
||||
// using category =
|
||||
// axis::category<std::string, axis::null_type, axis::option::growth>;
|
||||
using regular = axis::regular<double, def, def, axis::option::growth>;
|
||||
|
||||
// class custom_2d_axis {
|
||||
// public:
|
||||
// auto index(double x, double y) const {
|
||||
// const auto r = std::sqrt(x * x + y * y);
|
||||
// return std::min(static_cast<axis::index_type>(r), size());
|
||||
// }
|
||||
//
|
||||
// auto update(double x, double y) { const auto r = std::sqrt(x * x + y * y);
|
||||
// }
|
||||
//
|
||||
// axis::index_type size() const { return size_; }
|
||||
//
|
||||
// private:
|
||||
// axis::index_type size_ = 0;
|
||||
// };
|
||||
using integer = axis::integer<
|
||||
double, def,
|
||||
axis::join<axis::option::underflow, axis::option::overflow, axis::option::growth>>;
|
||||
|
||||
using category = axis::category<std::string, def, axis::option::growth>;
|
||||
|
||||
class custom_2d_axis {
|
||||
public:
|
||||
auto index(std::tuple<double, double> xy) const {
|
||||
const auto x = std::get<0>(xy);
|
||||
const auto y = std::get<1>(xy);
|
||||
const auto r = std::sqrt(x * x + y * y);
|
||||
return std::min(static_cast<axis::index_type>(r), size());
|
||||
}
|
||||
|
||||
auto update(std::tuple<double, double> xy) {
|
||||
const auto x = std::get<0>(xy);
|
||||
const auto y = std::get<1>(xy);
|
||||
const auto r = std::sqrt(x * x + y * y);
|
||||
const auto n = static_cast<int>(r);
|
||||
const auto old = size_;
|
||||
if (n >= size_) size_ = n + 1;
|
||||
return std::make_pair(n, old - size_);
|
||||
}
|
||||
|
||||
axis::index_type size() const { return size_; }
|
||||
|
||||
private:
|
||||
axis::index_type size_ = 0;
|
||||
};
|
||||
|
||||
template <typename Tag>
|
||||
void run_tests() {
|
||||
@ -74,75 +83,93 @@ void run_tests() {
|
||||
BOOST_TEST_EQ(h[4], 1);
|
||||
}
|
||||
|
||||
// {
|
||||
// auto h = make_s(Tag(), std::vector<int>(), integer());
|
||||
// const auto& a = h.axis();
|
||||
// h(-std::numeric_limits<double>::infinity());
|
||||
// h(std::numeric_limits<double>::quiet_NaN());
|
||||
// h(std::numeric_limits<double>::infinity());
|
||||
// BOOST_TEST_EQ(a.size(), 0);
|
||||
// BOOST_TEST_EQ(h.size(), 2);
|
||||
// BOOST_TEST_EQ(h[-1], 1);
|
||||
// BOOST_TEST_EQ(h[0], 2);
|
||||
// h(0);
|
||||
// BOOST_TEST_EQ(a.size(), 1);
|
||||
// BOOST_TEST_EQ(h.size(), 3);
|
||||
// BOOST_TEST_EQ(h[-1], 1);
|
||||
// BOOST_TEST_EQ(h[0], 1);
|
||||
// BOOST_TEST_EQ(h[1], 2);
|
||||
// h(2);
|
||||
// BOOST_TEST_EQ(a.size(), 3);
|
||||
// BOOST_TEST_EQ(h.size(), 5);
|
||||
// BOOST_TEST_EQ(h[-1], 1);
|
||||
// BOOST_TEST_EQ(h[0], 1);
|
||||
// BOOST_TEST_EQ(h[1], 0);
|
||||
// BOOST_TEST_EQ(h[2], 1);
|
||||
// BOOST_TEST_EQ(h[3], 2);
|
||||
// h(-2);
|
||||
// BOOST_TEST_EQ(a.size(), 5);
|
||||
// BOOST_TEST_EQ(h.size(), 7);
|
||||
// // BOOST_TEST_EQ(h[-1], 1)
|
||||
// BOOST_TEST_EQ(h[0], 1);
|
||||
// BOOST_TEST_EQ(h[1], 0);
|
||||
// BOOST_TEST_EQ(h[2], 1);
|
||||
// BOOST_TEST_EQ(h[3], 0);
|
||||
// BOOST_TEST_EQ(h[4], 1);
|
||||
// BOOST_TEST_EQ(h[5], 2);
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// auto h = make_s(Tag(), std::vector<int>(), integer(), category());
|
||||
// const auto& a = h.axis(0);
|
||||
// const auto& b = h.axis(1);
|
||||
// BOOST_TEST_EQ(a.size(), 0);
|
||||
// BOOST_TEST_EQ(b.size(), 0);
|
||||
// BOOST_TEST_EQ(h.size(), 0);
|
||||
// h(0, "x");
|
||||
// h(-std::numeric_limits<double>::infinity(), "x");
|
||||
// h(std::numeric_limits<double>::infinity(), "x");
|
||||
// h(std::numeric_limits<double>::quiet_NaN(), "x");
|
||||
// BOOST_TEST_EQ(a.size(), 1);
|
||||
// BOOST_TEST_EQ(b.size(), 1);
|
||||
// BOOST_TEST_EQ(h.size(), 3);
|
||||
// h(2, "x");
|
||||
// BOOST_TEST_EQ(a.size(), 3);
|
||||
// BOOST_TEST_EQ(b.size(), 1);
|
||||
// BOOST_TEST_EQ(h.size(), 5);
|
||||
// h(1, "y");
|
||||
// BOOST_TEST_EQ(a.size(), 3);
|
||||
// BOOST_TEST_EQ(b.size(), 2);
|
||||
// BOOST_TEST_EQ(h.size(), 10);
|
||||
// BOOST_TEST_EQ(h.at(-1, 0), 1);
|
||||
// BOOST_TEST_EQ(h.at(-1, 1), 0);
|
||||
// BOOST_TEST_EQ(h.at(3, 0), 2);
|
||||
// BOOST_TEST_EQ(h.at(3, 1), 0);
|
||||
// BOOST_TEST_EQ(h.at(a.index(0), b.index("x")), 1);
|
||||
// BOOST_TEST_EQ(h.at(a.index(1), b.index("x")), 0);
|
||||
// BOOST_TEST_EQ(h.at(a.index(2), b.index("x")), 1);
|
||||
// BOOST_TEST_EQ(h.at(a.index(0), b.index("y")), 0);
|
||||
// BOOST_TEST_EQ(h.at(a.index(1), b.index("y")), 1);
|
||||
// BOOST_TEST_EQ(h.at(a.index(2), b.index("y")), 0);
|
||||
// }
|
||||
{
|
||||
auto h = make_s(Tag(), std::vector<int>(), integer());
|
||||
const auto& a = h.axis();
|
||||
h(-std::numeric_limits<double>::infinity());
|
||||
h(std::numeric_limits<double>::quiet_NaN());
|
||||
h(std::numeric_limits<double>::infinity());
|
||||
BOOST_TEST_EQ(a.size(), 0);
|
||||
BOOST_TEST_EQ(h.size(), 2);
|
||||
BOOST_TEST_EQ(h[-1], 1);
|
||||
BOOST_TEST_EQ(h[0], 2);
|
||||
h(0);
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(h.size(), 3);
|
||||
BOOST_TEST_EQ(h[-1], 1);
|
||||
BOOST_TEST_EQ(h[0], 1);
|
||||
BOOST_TEST_EQ(h[1], 2);
|
||||
h(2);
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(h.size(), 5);
|
||||
BOOST_TEST_EQ(h[-1], 1);
|
||||
BOOST_TEST_EQ(h[0], 1);
|
||||
BOOST_TEST_EQ(h[1], 0);
|
||||
BOOST_TEST_EQ(h[2], 1);
|
||||
BOOST_TEST_EQ(h[3], 2);
|
||||
h(-2);
|
||||
BOOST_TEST_EQ(a.size(), 5);
|
||||
BOOST_TEST_EQ(h.size(), 7);
|
||||
// BOOST_TEST_EQ(h[-1], 1)
|
||||
BOOST_TEST_EQ(h[0], 1);
|
||||
BOOST_TEST_EQ(h[1], 0);
|
||||
BOOST_TEST_EQ(h[2], 1);
|
||||
BOOST_TEST_EQ(h[3], 0);
|
||||
BOOST_TEST_EQ(h[4], 1);
|
||||
BOOST_TEST_EQ(h[5], 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto h = make_s(Tag(), std::vector<int>(), integer(), category());
|
||||
const auto& a = h.axis(0);
|
||||
const auto& b = h.axis(1);
|
||||
BOOST_TEST_EQ(a.size(), 0);
|
||||
BOOST_TEST_EQ(b.size(), 0);
|
||||
BOOST_TEST_EQ(h.size(), 0);
|
||||
h(0, "x");
|
||||
h(-std::numeric_limits<double>::infinity(), "x");
|
||||
h(std::numeric_limits<double>::infinity(), "x");
|
||||
h(std::numeric_limits<double>::quiet_NaN(), "x");
|
||||
BOOST_TEST_EQ(a.size(), 1);
|
||||
BOOST_TEST_EQ(b.size(), 1);
|
||||
BOOST_TEST_EQ(h.size(), 3);
|
||||
h(2, "x");
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(b.size(), 1);
|
||||
BOOST_TEST_EQ(h.size(), 5);
|
||||
h(1, "y");
|
||||
BOOST_TEST_EQ(a.size(), 3);
|
||||
BOOST_TEST_EQ(b.size(), 2);
|
||||
BOOST_TEST_EQ(h.size(), 10);
|
||||
BOOST_TEST_EQ(h.at(-1, 0), 1);
|
||||
BOOST_TEST_EQ(h.at(-1, 1), 0);
|
||||
BOOST_TEST_EQ(h.at(3, 0), 2);
|
||||
BOOST_TEST_EQ(h.at(3, 1), 0);
|
||||
BOOST_TEST_EQ(h.at(a.index(0), b.index("x")), 1);
|
||||
BOOST_TEST_EQ(h.at(a.index(1), b.index("x")), 0);
|
||||
BOOST_TEST_EQ(h.at(a.index(2), b.index("x")), 1);
|
||||
BOOST_TEST_EQ(h.at(a.index(0), b.index("y")), 0);
|
||||
BOOST_TEST_EQ(h.at(a.index(1), b.index("y")), 1);
|
||||
BOOST_TEST_EQ(h.at(a.index(2), b.index("y")), 0);
|
||||
|
||||
BOOST_TEST_THROWS(h(0, "x", 42), std::invalid_argument);
|
||||
}
|
||||
|
||||
{
|
||||
auto h = make_s(Tag{}, std::vector<int>{}, custom_2d_axis{});
|
||||
BOOST_TEST_EQ(h.size(), 0);
|
||||
h(0, 0);
|
||||
BOOST_TEST_EQ(h.size(), 1);
|
||||
h(1, 0);
|
||||
h(0, 1);
|
||||
BOOST_TEST_EQ(h.size(), 2);
|
||||
h(10, 0);
|
||||
BOOST_TEST_EQ(h.size(), 11);
|
||||
BOOST_TEST_EQ(h[0], 1);
|
||||
BOOST_TEST_EQ(h[1], 2);
|
||||
BOOST_TEST_EQ(h[10], 1);
|
||||
BOOST_TEST_THROWS(h(0), std::invalid_argument);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
@ -62,7 +62,7 @@ void run_tests() {
|
||||
// copy_assign
|
||||
{
|
||||
auto a = make(T1{}, axis::regular<>{3, 0, 3}, axis::integer<>{0, 2});
|
||||
auto b = make_s(T2{}, std::vector<unsigned>(), axis::regular<>{3, 0, 3},
|
||||
auto b = make_s(T2{}, std::vector<double>(), axis::regular<>{3, 0, 3},
|
||||
axis::integer<>{0, 2});
|
||||
a(1, 1);
|
||||
BOOST_TEST_NE(a, b);
|
||||
|
@ -83,7 +83,7 @@ void run_tests() {
|
||||
a(0, weight(2));
|
||||
a(1, weight(2));
|
||||
auto b = a;
|
||||
auto c = make_s(Tag(), std::vector<unsigned>(), ia);
|
||||
auto c = make_s(Tag(), std::vector<int>(), ia);
|
||||
c(0, weight(2));
|
||||
c(1, weight(2));
|
||||
auto a2 = a;
|
||||
|
@ -17,14 +17,17 @@ template <typename Tag>
|
||||
void run_tests(const char* filename) {
|
||||
// histogram_serialization
|
||||
namespace tr = axis::transform;
|
||||
auto a =
|
||||
make(Tag(), axis::regular<>(3, -1, 1, "reg"), axis::circular<>(2, 0.0, 1.0, "cir"),
|
||||
axis::regular<double, tr::log>(3, 1, std::exp(2), "reg-log"),
|
||||
axis::regular<double, tr::pow, std::vector<int>, axis::option::overflow>(
|
||||
tr::pow(0.5), 3, 1, 100, {1, 2, 3}),
|
||||
axis::variable<>({1.0, 2.0, 3.0}, "var"), axis::category<>{3, 1, 2},
|
||||
axis::integer<int, axis::null_type>(0, 2));
|
||||
a(0.5, 0.2, 20, 20, 2.5, 1, 1);
|
||||
using def = use_default;
|
||||
using axis::option::none;
|
||||
auto a = make(Tag(), axis::regular<double, def, def, none>(1, -1, 1, "reg"),
|
||||
axis::circular<float, def, none>(1, 0.0, 1.0, "cir"),
|
||||
axis::regular<double, tr::log, def, none>(1, 1, std::exp(2), "reg-log"),
|
||||
axis::regular<double, tr::pow, std::vector<int>, axis::option::overflow>(
|
||||
tr::pow(0.5), 1, 1, 100, {1, 2, 3}),
|
||||
axis::variable<double, def, none>({1.5, 2.5}, "var"),
|
||||
axis::category<int, def, none>{3, 1},
|
||||
axis::integer<int, axis::null_type, none>(1, 2));
|
||||
a(0.5, 0.2, 2, 20, 2.2, 1, 1);
|
||||
print_xml(filename, a);
|
||||
|
||||
auto b = decltype(a)();
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
||||
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/histogram.hpp>
|
||||
#include <boost/histogram/accumulators/ostream.hpp>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
@ -109,7 +110,7 @@ void run_tests() {
|
||||
h2 = h;
|
||||
BOOST_TEST_EQ(h, h2);
|
||||
auto h3 = histogram<std::tuple<axis::integer<>, axis::integer<>>,
|
||||
storage_adaptor<std::vector<unsigned>>>();
|
||||
storage_adaptor<std::vector<double>>>();
|
||||
h3 = h;
|
||||
BOOST_TEST_EQ(h, h3);
|
||||
}
|
||||
@ -485,7 +486,7 @@ void run_tests() {
|
||||
BOOST_TEST_EQ(h.at(1, 0, 0), 1);
|
||||
}
|
||||
|
||||
// using static containers
|
||||
// using containers or input and output
|
||||
{
|
||||
auto h = make_s(Tag(), std::vector<accumulators::weighted_sum<>>(),
|
||||
axis::integer<>(0, 2), axis::regular<>(2, 2, 4));
|
||||
@ -501,6 +502,13 @@ void run_tests() {
|
||||
BOOST_TEST_EQ(h[i00].value(), 1);
|
||||
BOOST_TEST_EQ(h[i11].value(), 1);
|
||||
|
||||
// iterable out
|
||||
int j11[] = {1, 1};
|
||||
int j111[] = {1, 1, 1};
|
||||
BOOST_TEST_EQ(h.at(j11), 1);
|
||||
BOOST_TEST_EQ(h[j11], 1);
|
||||
BOOST_TEST_THROWS((void)h.at(j111), std::invalid_argument);
|
||||
|
||||
// tuple with weight
|
||||
h(std::make_tuple(weight(2), 0, 2.0));
|
||||
h(std::make_tuple(1, 3.0, weight(2)));
|
||||
|
@ -159,7 +159,7 @@ int main() {
|
||||
|
||||
mixed_tests<storage_adaptor<std::vector<int>>,
|
||||
storage_adaptor<std::array<double, 100>>>();
|
||||
mixed_tests<unlimited_storage<>, storage_adaptor<std::vector<int>>>();
|
||||
mixed_tests<unlimited_storage<>, storage_adaptor<std::vector<double>>>();
|
||||
mixed_tests<storage_adaptor<std::vector<int>>, unlimited_storage<>>();
|
||||
mixed_tests<storage_adaptor<std::vector<int>>,
|
||||
storage_adaptor<std::map<std::size_t, int>>>();
|
||||
|
@ -101,7 +101,7 @@ void increase_and_grow() {
|
||||
++x[0];
|
||||
n2[0] += x[0];
|
||||
|
||||
double v = tmax;
|
||||
auto v = static_cast<double>(tmax);
|
||||
++v;
|
||||
BOOST_TEST_EQ(n[0], v);
|
||||
BOOST_TEST_EQ(n2[0], v);
|
||||
@ -216,47 +216,41 @@ int main() {
|
||||
c = 0;
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 255u), true);
|
||||
BOOST_TEST_EQ(c, 255);
|
||||
c = 0;
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 255), true);
|
||||
BOOST_TEST_EQ(c, 255);
|
||||
c = 1;
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 255), false);
|
||||
BOOST_TEST_EQ(c, 1);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 255u), false);
|
||||
BOOST_TEST_EQ(c, 1);
|
||||
c = 255;
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 1u), false);
|
||||
BOOST_TEST_EQ(c, 255);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, 1), false);
|
||||
BOOST_TEST_EQ(c, 255);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, -255), true);
|
||||
BOOST_TEST_EQ(c, 0);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(c, -1), false);
|
||||
BOOST_TEST_EQ(c, 0);
|
||||
|
||||
uint32_t i = 0;
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(i, 2), true);
|
||||
BOOST_TEST_EQ(i, 2u);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(i, -2), true);
|
||||
BOOST_TEST_EQ(i, 0u);
|
||||
BOOST_TEST_EQ(bh::detail::safe_radd(i, -2), false);
|
||||
BOOST_TEST_EQ(i, 0u);
|
||||
}
|
||||
|
||||
// mp_int
|
||||
{
|
||||
const auto vmax = max<uint64_t>();
|
||||
|
||||
BOOST_TEST_EQ(mp_int(), 0);
|
||||
BOOST_TEST_EQ(mp_int(), 0.0);
|
||||
BOOST_TEST_EQ(mp_int(1), 1);
|
||||
BOOST_TEST_NE(mp_int(1), 2);
|
||||
BOOST_TEST_LT(mp_int(1), 2);
|
||||
BOOST_TEST_LE(mp_int(1), 2);
|
||||
BOOST_TEST_LE(mp_int(1), 1);
|
||||
BOOST_TEST_GT(mp_int(1), 0);
|
||||
BOOST_TEST_GE(mp_int(1), 0);
|
||||
BOOST_TEST_GE(mp_int(1), 1);
|
||||
BOOST_TEST_EQ(mp_int(), 0u);
|
||||
BOOST_TEST_EQ(mp_int(1u), 1u);
|
||||
BOOST_TEST_EQ(mp_int(1u), 1.0);
|
||||
BOOST_TEST_EQ(mp_int(1u), mp_int(1u));
|
||||
BOOST_TEST_NE(mp_int(1u), 2u);
|
||||
BOOST_TEST_NE(mp_int(1u), 2.0);
|
||||
BOOST_TEST_NE(mp_int(1u), mp_int(2u));
|
||||
BOOST_TEST_LT(mp_int(1u), 2u);
|
||||
BOOST_TEST_LT(mp_int(1u), 2.0);
|
||||
BOOST_TEST_LT(mp_int(1u), mp_int(2u));
|
||||
BOOST_TEST_LE(mp_int(1u), 2u);
|
||||
BOOST_TEST_LE(mp_int(1u), 2.0);
|
||||
BOOST_TEST_LE(mp_int(1u), mp_int(2u));
|
||||
BOOST_TEST_LE(mp_int(1u), 1u);
|
||||
BOOST_TEST_GT(mp_int(1u), 0u);
|
||||
BOOST_TEST_GT(mp_int(1u), 0.0);
|
||||
BOOST_TEST_GT(mp_int(1u), mp_int(0u));
|
||||
BOOST_TEST_GE(mp_int(1u), 0u);
|
||||
BOOST_TEST_GE(mp_int(1u), 0.0);
|
||||
BOOST_TEST_GE(mp_int(1u), 1u);
|
||||
BOOST_TEST_GE(mp_int(1u), mp_int(0u));
|
||||
BOOST_TEST_NOT(mp_int(1u) < mp_int(1u));
|
||||
BOOST_TEST_NOT(mp_int(1u) > mp_int(1u));
|
||||
|
||||
auto a = mp_int();
|
||||
++a;
|
||||
@ -268,24 +262,34 @@ int main() {
|
||||
BOOST_TEST_EQ(a, vmax);
|
||||
BOOST_TEST_EQ(a, static_cast<double>(vmax));
|
||||
++a;
|
||||
BOOST_TEST_EQ(a.data.size(), 2);
|
||||
BOOST_TEST_EQ(a.data[0], 0);
|
||||
BOOST_TEST_EQ(a.data[1], 1);
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 1));
|
||||
++a;
|
||||
BOOST_TEST_EQ(a.data.size(), 2);
|
||||
BOOST_TEST_EQ(a.data[0], 1);
|
||||
BOOST_TEST_EQ(a.data[1], 1);
|
||||
BOOST_TEST_EQ(a, make_mp_int(1, 1));
|
||||
a += a;
|
||||
BOOST_TEST_EQ(a.data.size(), 2);
|
||||
BOOST_TEST_EQ(a.data[0], 2);
|
||||
BOOST_TEST_EQ(a.data[1], 2);
|
||||
BOOST_TEST_EQ(a, make_mp_int(2, 2));
|
||||
BOOST_TEST_EQ(a, 2 * static_cast<double>(vmax) + 2);
|
||||
|
||||
// carry once A
|
||||
a.data[0] = vmax;
|
||||
a.data[1] = 1;
|
||||
++a;
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 2));
|
||||
// carry once B
|
||||
a.data[0] = vmax;
|
||||
a.data[1] = 1;
|
||||
a += 1;
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 2));
|
||||
// carry once C
|
||||
a.data[0] = vmax;
|
||||
a.data[1] = 1;
|
||||
a += make_mp_int(1, 1);
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 3));
|
||||
|
||||
a.data[0] = vmax - 1;
|
||||
a.data[1] = vmax;
|
||||
++a;
|
||||
BOOST_TEST_EQ(a.data.size(), 2);
|
||||
BOOST_TEST_EQ(a.data[0], vmax);
|
||||
BOOST_TEST_EQ(a.data[1], vmax);
|
||||
BOOST_TEST_EQ(a, make_mp_int(vmax, vmax));
|
||||
|
||||
// carry two times A
|
||||
++a;
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 0, 1));
|
||||
@ -298,6 +302,7 @@ int main() {
|
||||
a += mp_int(1);
|
||||
BOOST_TEST_EQ(a, make_mp_int(0, 0, 1));
|
||||
|
||||
// carry and enlarge
|
||||
a = make_mp_int(vmax, vmax);
|
||||
a += a;
|
||||
BOOST_TEST_EQ(a, make_mp_int(vmax - 1, vmax, 1));
|
||||
@ -321,7 +326,7 @@ int main() {
|
||||
a += a;
|
||||
BOOST_TEST_EQ(a, b);
|
||||
}
|
||||
BOOST_TEST_GT(a.data.size(), 1);
|
||||
BOOST_TEST_GT(a.data.size(), 1u);
|
||||
}
|
||||
|
||||
// empty state
|
||||
|
Loading…
x
Reference in New Issue
Block a user