WaveBlocksND
shape_enum_union.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <vector>
5 #include <utility>
6 #include <initializer_list>
7 
8 #include "shape_enum.hpp"
9 
10 
11 namespace waveblocks {
12  namespace wavepackets {
13  namespace shapes {
14  namespace shape_enum {
34  template<class Input1, class Input2, class Output, class Compare>
35  Output strict_union(Input1 begin1, Input1 end1, Input2 begin2, Input2 end2, Output sink, Compare less)
36  {
37  auto it1 = begin1;
38  auto it2 = begin2;
39 
40  while (it1 != end1 && it2 != end2) {
41  if (*it1 == *it2) {
42  // lhs = rhs
43  *sink = *it1;
44  ++it1;
45  ++it2;
46  ++sink;
47  }
48  else if ( less(*it1, *it2) ) {
49  // lhs < rhs
50  *sink = *it1;
51  ++it1;
52  ++sink;
53  }
54  else {
55  // lhs > rhs
56  *sink = *it2;
57  ++it2;
58  ++sink;
59  }
60  }
61 
62  sink = std::copy(it1, end1, sink);
63  sink = std::copy(it2, end2, sink);
64 
65  return sink;
66  }
67 
68  template<class MultiIndex>
70  {
71  public:
72  MultiIndex value;
73  std::size_t source;
74 
75  bool operator<(const _strict_union__heap_entry& lhs) const
76  {
77  // this operator is used for heap construction
78  // the heap puts the largest value on top but we want the smallest value on top because
79  // the resulting enumeration must be sorted in ascending order
80  // therefore this operator does the opposite, namely 'LHS >= RHS' instead of 'LHS < RHS'
81  std::less<MultiIndex> less;
82  return less(lhs.value, value);
83  }
84  };
85 
89  template<class MultiIndex>
90  std::vector<MultiIndex> strict_union(std::vector< typename std::vector<MultiIndex>::const_iterator > begin,
91  std::vector< typename std::vector<MultiIndex>::const_iterator > end)
92  {
93  assert( begin.size() == end.size() );
94 
95  typedef _strict_union__heap_entry<MultiIndex> HeapEntry;
96 
97  // get size of largest source
98  std::size_t minsize = 0;
99  for (std::size_t i = 0; i < begin.size(); i++) {
100  minsize = std::max(minsize, static_cast<std::size_t>(end[i] - begin[i]));
101  }
102 
103  std::vector<MultiIndex> superset;
104  std::vector< HeapEntry > heap; // tuple (multi-index, source)
105 
106  // initialize heap
107  for (std::size_t i = 0; i < begin.size(); i++) {
108  if (begin[i] != end[i]) {
109  heap.push_back( HeapEntry{*(begin[i]), i} );
110  std::push_heap(heap.begin(), heap.end());
111  (begin[i])++;
112  }
113  }
114  std::make_heap(heap.begin(), heap.end());
115 
116  // merge multi-indices
117  while (!heap.empty()) {
118  HeapEntry entry = heap.front();
119  std::pop_heap(heap.begin(), heap.end()); heap.pop_back();
120 
121  if (superset.empty() || entry.value != superset.back()) {
122  std::less<MultiIndex> less;
123 
124  (void)less;
125  assert( superset.empty() || less(superset.back(), entry.value) ); // multi-indices must be sorted in ascending order
126  superset.push_back(entry.value);
127  }
128 
129  if ( begin[entry.source] != end[entry.source] ) {
130  heap.push_back( HeapEntry{*(begin[entry.source]), entry.source} );
131  std::push_heap(heap.begin(), heap.end());
132  (begin[entry.source])++;
133  }
134  }
135 
136  return superset;
137  }
138 
139  template<dim_t D, class MultiIndex>
140  ShapeSlice<D, MultiIndex> strict_union(const std::vector< const ShapeSlice<D, MultiIndex>* >& slices, std::size_t union_offset)
141  {
142  std::vector< typename std::vector<MultiIndex>::const_iterator > begin(slices.size());
143  std::vector< typename std::vector<MultiIndex>::const_iterator > end(slices.size());
144 
145  for (std::size_t i = 0; i < slices.size(); i++) {
146  begin[i] = slices[i]->cbegin();
147  end[i] = slices[i]->cend();
148  }
149 
150  std::vector<MultiIndex> superset = strict_union<MultiIndex>(begin, end);
151 
152  return {std::move(superset), union_offset};
153  }
154 
155  template<dim_t D, class MultiIndex>
157  {
158  // determine number of slices in union
159  int n_slices = 0;
160  MultiIndex limits{};
161  for (auto _enum : enums) {
162  n_slices = std::max(n_slices, _enum->n_slices());
163  for (dim_t d = 0; d < D; d++) {
164  limits[d] = std::max((int)limits[d], _enum->limit(d));
165  }
166  }
167 
168  // create union
169  std::size_t offset = 0;
170  std::vector< ShapeSlice<D,MultiIndex> > superset(n_slices);
171  for (int islice = 0; islice < n_slices; islice++) {
172  std::vector< const ShapeSlice<D, MultiIndex>* > slices;
173  for (std::size_t source = 0; source < enums.size(); source++) {
174  auto slice = &enums[source]->slice(islice);
175  if (slice->size() != 0) {
176  slices.push_back(slice);
177  }
178  }
179  superset[islice] = strict_union<D,MultiIndex>(slices, offset);
180  offset += superset[islice].size();
181  }
182 
183  return {std::move(superset), offset, limits};
184  }
185 
191  template<dim_t D, class MultiIndex, std::size_t N>
193  {
194  std::vector< const ShapeEnum<D, MultiIndex>* > enum_vec(enum_list.cbegin(), enum_list.cend());
195  return strict_union<D,MultiIndex>(enum_vec);
196  }
197 
202  template<dim_t D, class MultiIndex, std::size_t N>
203  ShapeEnum<D, MultiIndex> strict_union(const std::array< const ShapeEnum<D, MultiIndex>*, N >& enum_list)
204  {
205  std::vector< const ShapeEnum<D, MultiIndex>* > enum_vec(enum_list.cbegin(), enum_list.cend());
206  return strict_union<D,MultiIndex>(enum_vec);
207  }
208 
213  template<dim_t D, class MultiIndex>
214  ShapeEnum<D, MultiIndex> strict_union(std::initializer_list< const ShapeEnum<D, MultiIndex>* > enum_list)
215  {
216  std::vector< const ShapeEnum<D, MultiIndex>* > enum_vec(enum_list);
217  return strict_union<D,MultiIndex>(enum_vec);
218  }
219  }
220  }
221  }
222 }
Definition: coefficients_file_parser.cpp:10
std::size_t source
Definition: shape_enum_union.hpp:73
MultiIndex value
Definition: shape_enum_union.hpp:72
Output strict_union(Input1 begin1, Input1 end1, Input2 begin2, Input2 end2, Output sink, Compare less)
Creates union of two shape slices.
Definition: shape_enum_union.hpp:35
A shape enumeration is a complete, ordered list of all lattice nodes that are part of the basis shape...
Definition: shape_enum.hpp:353
bool operator<(const _strict_union__heap_entry &lhs) const
Definition: shape_enum_union.hpp:75
The -th slice of a shape enumeration contains all multi-indices that satisfy .
Definition: shape_enum.hpp:18
Definition: shape_enum_union.hpp:69
int dim_t
Definition: types.hpp:16