Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:12

0001 // Copyright 2020 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_REDUCE_COMMAND_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_REDUCE_COMMAND_HPP
0009 
0010 #include <boost/core/span.hpp>
0011 #include <boost/histogram/fwd.hpp>
0012 #include <boost/throw_exception.hpp>
0013 #include <cassert>
0014 #include <stdexcept>
0015 #include <string>
0016 
0017 namespace boost {
0018 namespace histogram {
0019 namespace detail {
0020 
0021 struct reduce_command {
0022   static constexpr unsigned unset = static_cast<unsigned>(-1);
0023   unsigned iaxis = unset;
0024   enum class range_t : char {
0025     none,
0026     indices,
0027     values,
0028   } range = range_t::none;
0029   union {
0030     axis::index_type index;
0031     double value;
0032   } begin{0}, end{0};
0033   unsigned merge = 0; // default value indicates unset option
0034   bool crop = false;
0035   // for internal use by the reduce algorithm
0036   bool is_ordered = true;
0037   bool use_underflow_bin = true;
0038   bool use_overflow_bin = true;
0039 };
0040 
0041 // - puts commands in correct axis order
0042 // - sets iaxis for positional commands
0043 // - detects and fails on invalid settings
0044 // - fuses merge commands with non-merge commands
0045 inline void normalize_reduce_commands(span<reduce_command> out,
0046                                       span<const reduce_command> in) {
0047   unsigned iaxis = 0;
0048   for (const auto& o_in : in) {
0049     assert(o_in.merge > 0);
0050     if (o_in.iaxis != reduce_command::unset && o_in.iaxis >= out.size())
0051       BOOST_THROW_EXCEPTION(std::invalid_argument("invalid axis index"));
0052     auto& o_out = out.begin()[o_in.iaxis == reduce_command::unset ? iaxis : o_in.iaxis];
0053     if (o_out.merge == 0) {
0054       o_out = o_in;
0055     } else {
0056       // Some command was already set for this axis, try to fuse commands.
0057       if (!((o_in.range == reduce_command::range_t::none) ^
0058             (o_out.range == reduce_command::range_t::none)) ||
0059           (o_out.merge > 1 && o_in.merge > 1))
0060         BOOST_THROW_EXCEPTION(std::invalid_argument(
0061             "multiple conflicting reduce commands for axis " +
0062             std::to_string(o_in.iaxis == reduce_command::unset ? iaxis : o_in.iaxis)));
0063       if (o_in.range != reduce_command::range_t::none) {
0064         o_out.range = o_in.range;
0065         o_out.begin = o_in.begin;
0066         o_out.end = o_in.end;
0067       } else {
0068         o_out.merge = o_in.merge;
0069       }
0070     }
0071     ++iaxis;
0072   }
0073 
0074   iaxis = 0;
0075   for (auto& o : out) o.iaxis = iaxis++;
0076 }
0077 
0078 } // namespace detail
0079 } // namespace histogram
0080 } // namespace boost
0081 
0082 #endif