improving and testing operators

This commit is contained in:
Hans Dembinski 2017-11-05 23:44:37 +01:00
parent 371cbc9385
commit 5dee79f556
6 changed files with 96 additions and 30 deletions

View File

@ -13,7 +13,6 @@
#include <boost/iterator/iterator_facade.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/operators.hpp>
#include <boost/utility/string_view.hpp>
#include <cmath>
#include <limits>
@ -127,7 +126,7 @@ protected:
return *this;
}
bool operator==(const axis_base &rhs) const {
bool operator==(const axis_base &rhs) const noexcept {
return size_ == rhs.size_ && label_ == rhs.label_;
}
@ -167,7 +166,7 @@ protected:
return *this;
}
bool operator==(const axis_base_uoflow &rhs) const {
bool operator==(const axis_base_uoflow &rhs) const noexcept {
return axis_base::operator==(rhs) && shape_ == rhs.shape_;
}
@ -182,28 +181,28 @@ namespace transform {
struct identity {
template <typename T> static T forward(T v) { return v; }
template <typename T> static T inverse(T v) { return v; }
bool operator==(const identity &) const { return true; }
bool operator==(const identity &) const noexcept { return true; }
template <class Archive> void serialize(Archive &, unsigned) {}
};
struct log {
template <typename T> static T forward(T v) { return std::log(v); }
template <typename T> static T inverse(T v) { return std::exp(v); }
bool operator==(const log &) const { return true; }
bool operator==(const log &) const noexcept { return true; }
template <class Archive> void serialize(Archive &, unsigned) {}
};
struct sqrt {
template <typename T> static T forward(T v) { return std::sqrt(v); }
template <typename T> static T inverse(T v) { return v * v; }
bool operator==(const sqrt &) const { return true; }
bool operator==(const sqrt &) const noexcept { return true; }
template <class Archive> void serialize(Archive &, unsigned) {}
};
struct cos {
template <typename T> static T forward(T v) { return std::cos(v); }
template <typename T> static T inverse(T v) { return std::acos(v); }
bool operator==(const cos &) const { return true; }
bool operator==(const cos &) const noexcept { return true; }
template <class Archive> void serialize(Archive &, unsigned) {}
};
@ -215,7 +214,7 @@ struct pow {
return std::pow(v, 1.0 / value);
}
double value = 1.0;
bool operator==(const pow &other) const { return value == other.value; }
bool operator==(const pow &other) const noexcept { return value == other.value; }
template <class Archive> void serialize(Archive &, unsigned);
};
} // namespace transform
@ -226,8 +225,7 @@ struct pow {
* Very fast. Binning is a O(1) operation.
*/
template <typename RealType = double, typename Transform = transform::identity>
class regular : public axis_base_uoflow, Transform,
boost::operators<regular<RealType, Transform>> {
class regular : public axis_base_uoflow, Transform {
public:
using value_type = RealType;
using bin_type = interval<value_type>;
@ -315,7 +313,7 @@ private:
* bins for this axis. Binning is a O(1) operation.
*/
template <typename RealType = double>
class circular : public axis_base, boost::operators<regular<RealType>> {
class circular : public axis_base {
public:
using value_type = RealType;
using bin_type = interval<value_type>;
@ -355,7 +353,7 @@ public:
return {eval(idx), eval(idx + 1)};
}
bool operator==(const circular &o) const {
bool operator==(const circular &o) const noexcept {
return axis_base::operator==(o) && phase_ == o.phase_ &&
perimeter_ == o.perimeter_;
}
@ -380,7 +378,7 @@ private:
* and the problem domain allows it, prefer a regular.
*/
template <typename RealType = double>
class variable : public axis_base_uoflow, boost::operators<variable<RealType>> {
class variable : public axis_base_uoflow {
public:
using value_type = RealType;
using bin_type = interval<value_type>;
@ -448,7 +446,7 @@ public:
return {eval(idx), eval(idx + 1)};
}
bool operator==(const variable &o) const {
bool operator==(const variable &o) const noexcept {
if (!axis_base_uoflow::operator==(o)) {
return false;
}
@ -476,7 +474,7 @@ private:
* faster than a regular.
*/
template <typename IntType = int>
class integer : public axis_base_uoflow, boost::operators<integer<IntType>> {
class integer : public axis_base_uoflow {
public:
using value_type = IntType;
using bin_type = interval<value_type>;
@ -510,7 +508,7 @@ public:
/// Returns the integer that is mapped to the bin index.
bin_type operator[](int idx) const { return {min_ + idx, min_ + idx + 1}; }
bool operator==(const integer &o) const {
bool operator==(const integer &o) const noexcept {
return axis_base_uoflow::operator==(o) && min_ == o.min_;
}
@ -537,7 +535,7 @@ private:
* Binning is a O(1) operation. The value type must be hashable.
*/
template <typename T = int>
class category : public axis_base, boost::operators<category<T>> {
class category : public axis_base {
using map_type = bimap<T, int>;
public:
@ -597,9 +595,9 @@ public:
return it->second;
}
bool operator==(const category &other) const {
return axis_base::operator==(other) &&
std::equal(map_->begin(), map_->end(), other.map_->begin());
bool operator==(const category &o) const noexcept {
return axis_base::operator==(o) &&
std::equal(map_->begin(), map_->end(), o.map_->begin());
}
const_iterator begin() const { return const_iterator(*this, 0); }

View File

@ -43,13 +43,16 @@ template <typename T, typename = decltype(std::begin(std::declval<T &>()),
std::end(std::declval<T &>()))>
struct is_sequence {};
template <typename MainVector, typename AuxVector> struct combine {
template <typename MainVector, typename AuxVector> struct combiner {
using type =
typename mpl::copy_if<AuxVector,
mpl::not_<mpl::contains<MainVector, mpl::_1>>,
mpl::back_inserter<MainVector>>::type;
};
template <typename MainVector, typename AuxVector>
using combine = typename combiner<MainVector, AuxVector>::type;
struct bool_mask_op {
std::vector<bool> &b;
bool v;

View File

@ -65,6 +65,47 @@ inline detail::keep_dynamic keep(unsigned i, Rest... rest) {
return s;
}
// fast operators (boost::operators does not use rvalue references yet)
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> && operator+(histogram<Variant, Axes, Storage> &&a,
const histogram<Variant, Axes, Storage> &b)
{ a+=b; return std::move(a); }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>&& operator+(histogram<Variant, Axes, Storage> &&a,
histogram<Variant, Axes, Storage> &&b)
{ a+=b; return std::move(a); }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>&& operator+(const histogram<Variant, Axes, Storage> &a,
histogram<Variant, Axes, Storage> &&b)
{ b+=a; return std::move(b); }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> operator+(const histogram<Variant, Axes, Storage> &a,
const histogram<Variant, Axes, Storage> &b)
{ histogram<Variant, Axes, Storage> r(a); r+=b; return r; }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>&& operator*(histogram<Variant, Axes, Storage> &&a,
const double x)
{ a*=x; return std::move(a); }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage>&& operator*(const double x,
histogram<Variant, Axes, Storage> &&b)
{ b*=x; return std::move(b); }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> operator*(const histogram<Variant, Axes, Storage> &a,
const double x)
{ histogram<Variant, Axes, Storage> r(a); r*=x; return r; }
template <typename Variant, typename Axes, typename Storage>
histogram<Variant, Axes, Storage> operator*(const double x,
const histogram<Variant, Axes, Storage> &b)
{ histogram<Variant, Axes, Storage> r(b); r*=x; return r; }
} // namespace histogram
} // namespace boost

View File

@ -431,22 +431,22 @@ private:
template <typename... Axes>
inline histogram<
Dynamic, typename detail::combine<builtin_axes, mpl::vector<Axes...>>::type>
Dynamic, detail::combine<builtin_axes, mpl::vector<Axes...>>>
make_dynamic_histogram(Axes &&... axes) {
return histogram<Dynamic, typename detail::combine<
builtin_axes, mpl::vector<Axes...>>::type>(
return histogram<Dynamic, detail::combine<
builtin_axes, mpl::vector<Axes...>>>(
std::forward<Axes>(axes)...);
}
template <typename Storage, typename... Axes>
inline histogram<
Dynamic, typename detail::combine<builtin_axes, mpl::vector<Axes...>>::type,
Dynamic, detail::combine<builtin_axes, mpl::vector<Axes...>>,
Storage>
make_dynamic_histogram_with(Axes &&... axes) {
return histogram<
Dynamic,
typename detail::combine<builtin_axes, mpl::vector<Axes...>>::type,
detail::combine<builtin_axes, mpl::vector<Axes...>>,
Storage>(std::forward<Axes>(axes)...);
}

View File

@ -7,8 +7,6 @@
#ifndef _BOOST_HISTOGRAM_HISTOGRAM_IMPL_STATIC_HPP_
#define _BOOST_HISTOGRAM_HISTOGRAM_IMPL_STATIC_HPP_
#include <boost/call_traits.hpp>
#include <boost/config.hpp>
#include <boost/fusion/adapted/mpl.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>

View File

@ -532,6 +532,32 @@ template <typename Type> void run_tests() {
BOOST_TEST_EQ(h.sum(), 20.0);
}
// operators
{
auto a = make_histogram<adaptive_storage>(Type(), axis::integer<>(0, 3));
auto b = a;
a.fill(0);
b.fill(1);
auto c = a + b;
BOOST_TEST_EQ(c.value(0), 1.0);
BOOST_TEST_EQ(c.value(1), 1.0);
c += b;
BOOST_TEST_EQ(c.value(0), 1.0);
BOOST_TEST_EQ(c.value(1), 2.0);
auto d = 3 * a;
auto e = b * 2;
BOOST_TEST_EQ(d.value(0), 3.0);
BOOST_TEST_EQ(d.value(1), 0.0);
BOOST_TEST_EQ(e.value(0), 0.0);
BOOST_TEST_EQ(e.value(1), 2.0);
auto r = a;
r += b;
r += d;
BOOST_TEST_EQ(r.value(0), 4.0);
BOOST_TEST_EQ(r.value(1), 1.0);
BOOST_TEST_EQ(r, a + b + 3 * a);
}
// histogram_serialization
{
enum { A, B, C };
@ -679,7 +705,7 @@ template <typename T1, typename T2> void run_mixed_tests() {
{
auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2));
auto b = make_histogram<adaptive_storage>(T2{}, axis::regular<>{3, 0, 3},
auto b = make_histogram<array_storage<int>>(T2{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2));
BOOST_TEST_EQ(a, b);
auto b2 = make_histogram<adaptive_storage>(T2{}, axis::integer<>{0, 3},
@ -694,7 +720,7 @@ template <typename T1, typename T2> void run_mixed_tests() {
{
auto a = make_histogram<adaptive_storage>(T1{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2));
auto b = make_histogram<adaptive_storage>(T2{}, axis::regular<>{3, 0, 3},
auto b = make_histogram<array_storage<int>>(T2{}, axis::regular<>{3, 0, 3},
axis::integer<>(0, 2));
a.fill(1, 1);
BOOST_TEST_NE(a, b);