GCC Code Coverage Report


Directory: ./
File: include/na64util/cartesian-product.hh
Date: 2025-09-01 06:19:01
Exec Total Coverage
Lines: 23 23 100.0%
Functions: 6 6 100.0%
Branches: 9 10 90.0%

Line Branch Exec Source
1 #pragma once
2
3 #include <array>
4 #include <vector>
5 #include <cassert>
6 #include <memory>
7
8 #include "na64util/array-unwinding.hh"
9
10 namespace na64dp {
11 namespace util {
12
13 /**\brief Helper class representing stateful generator for cartesian product
14 *
15 * Initialized with a sequence of homogeneous STL containers, implements an
16 * iterator over cartesian product results (pairs, triplets, quadruplets, etc).
17 *
18 * \ingroup numerical-utils
19 * */
20 template<Arity_t NT, typename SeqT>
21 class CartesianProduct {
22 private:
23 /// Set of ends for hits collections
24 std::array<typename SeqT::const_iterator, NT> _begins
25 , _state
26 , _ends
27 ;
28 public:
29 template<typename ... ArgsT>
30 4 CartesianProduct( ArgsT & ... args ) : _begins{args.begin()...}
31 4 , _state(_begins)
32 4 , _ends{args.end()...}
33 4 {}
34 CartesianProduct( CartesianProduct<NT, SeqT> && o)
35 : _begins(std::move(o._begins))
36 , _state(std::move(o._state))
37 , _ends(std::move(o._ends)) {}
38 /// Writes set of IDs to given destination, if possible. If not,
39 /// returns `false`
40 12 bool operator>>(std::array<typename SeqT::value_type, NT> & dest) {
41
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 10 times.
42 for( Arity_t i = 0; i < NT; ++i ) {
42
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 30 times.
32 if( _ends[i] == _state[i] ) return false;
43 30 dest[i] = *_state[i];
44 }
45 10 ++_state[NT-1];
46 // advance states
47
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 3 times.
18 for( Arity_t i = NT-1; i != 0; --i) {
48
2/2
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 8 times.
15 if( _state[i] != _ends[i] ) break;
49 8 _state[i] = _begins[i];
50 8 ++_state[i-1];
51 }
52 10 return true;
53 }
54
55 void reset() { _state = _begins; }
56 };
57
58 template<typename ObjectT, typename ArgT, Arity_t... Ns> ObjectT
59 1 unwind_array_to_constructor( const ArgT && arg, std::index_sequence<Ns...> ) {
60 1 return ObjectT( std::move(arg [Ns]) ... );
61 }
62
63 template<typename ObjectT, typename ArgT, Arity_t... Ns> std::shared_ptr<ObjectT>
64 unwind_array_to_constructor_shared( ArgT && arg, std::index_sequence<Ns...> ) {
65 return std::shared_ptr<ObjectT>( std::move(arg [Ns]) ... );
66 }
67
68 //template<typename ObjectT, typename ArgT, Arity_t... Ns> ObjectT
69 //unwind_array_to_constructor( const ArgT & arg, std::index_sequence<Ns...> ) {
70 // return ObjectT( arg [Ns] ... );
71 //}
72 //
73 //template<typename ArgT, typename CallableT, Arity_t... Ns> auto
74 //unwind_array_to_call( CallableT c, const ArgT & arg, std::index_sequence<Ns...> ) {
75 // return c( arg [Ns] ... );
76 //}
77
78 /**\brief Product result in array of fixed arity
79 *
80 * \ingroup numerical-utils
81 * */
82 template<typename T, Arity_t NT>
83 struct CartesianProductCollections : protected std::array<std::vector<T>, NT> {
84 /// Adds new element into n-th set
85 5 void add(Arity_t n, const T & element) {
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(n < NT);
87 5 std::array<std::vector<T>, NT>::operator[](n).push_back(element);
88 5 }
89 /// Clears collected sets
90 void clear() {
91 for(Arity_t n = 0; n < NT; ++n) {
92 std::array<std::vector<T>, NT>::operator[](n).clear();
93 }
94 }
95
96 1 auto get() const {
97 return unwind_array_to_constructor< CartesianProduct< NT, std::vector<T> >
98 , std::array<std::vector<T>, NT>
99 1 >( std::move(static_cast<const std::array<std::vector<T>, NT>&>(*this))
100 1 , std::make_integer_sequence<Arity_t, NT>{} );
101 }
102 };
103
104 } // namespace ::na64dp::util
105 } // namespace na64dp
106
107