18 #ifndef TLX_ALGORITHM_MULTISEQUENCE_SELECTION_HEADER 19 #define TLX_ALGORITHM_MULTISEQUENCE_SELECTION_HEADER 35 namespace multisequence_selection_detail {
38 template <
typename T1,
typename T2,
typename Comparator>
48 const std::pair<T1, T2>& p2) {
49 if (
comp_(p1.first, p2.first))
52 if (
comp_(p2.first, p1.first))
56 return p1.second < p2.second;
61 template <
typename T1,
typename T2,
typename Comparator>
71 const std::pair<T1, T2>& p2) {
72 if (
comp_(p2.first, p1.first))
75 if (
comp_(p1.first, p2.first))
79 return p2.second < p1.second;
98 template <
typename ValueType,
typename RanSeqs,
typename RankType,
99 typename Comparator = std::less<ValueType> >
101 const RanSeqs& begin_seqs,
const RanSeqs& end_seqs,
102 const RankType& rank,
104 Comparator comp = Comparator()) {
106 using iterator =
typename std::iterator_traits<RanSeqs>
107 ::value_type::first_type;
108 using diff_type =
typename std::iterator_traits<iterator>
111 using SamplePair = std::pair<ValueType, diff_type>;
113 using namespace multisequence_selection_detail;
116 lexicographic<ValueType, diff_type, Comparator> lcomp(comp);
117 lexicographic_rev<ValueType, diff_type, Comparator> lrcomp(comp);
121 const diff_type m = std::distance(begin_seqs, end_seqs);
125 for (diff_type i = 0; i < m; ++i)
126 N += std::distance(begin_seqs[i].first, begin_seqs[i].second);
128 if (m == 0 || N == 0 || rank < 0 || rank >= N)
130 throw std::exception();
134 seqlen[0] = std::distance(begin_seqs[0].first, begin_seqs[0].second);
136 for (diff_type i = 1; i < m; ++i)
138 seqlen[i] = std::distance(begin_seqs[i].first, begin_seqs[i].second);
148 for (diff_type i = 0; i < m; ++i)
158 std::vector<SamplePair> sample;
160 for (diff_type i = 0; i < m; ++i) {
162 sample.push_back(SamplePair(begin_seqs[i].first[n], i));
165 std::sort(sample.begin(), sample.end(), lcomp);
167 for (diff_type i = 0; i < m; ++i) {
171 SamplePair(begin_seqs[i].first[0] , i));
174 size_t localrank =
static_cast<size_t>(rank / l);
177 for (j = 0; j < localrank && ((n + 1) <= seqlen[sample[j].second]); ++j)
178 a[sample[j].second] += n + 1;
179 for ( ; j < static_cast<size_t>(m); ++j)
180 b[sample[j].second] -= n + 1;
188 const ValueType* lmax =
nullptr;
189 for (diff_type i = 0; i < m; ++i)
195 lmax = &(begin_seqs[i].first[a[i] - 1]);
200 if (comp(*lmax, begin_seqs[i].first[a[i] - 1]))
201 lmax = &(begin_seqs[i].first[a[i] - 1]);
206 for (diff_type i = 0; i < m; ++i)
208 diff_type middle = (b[i] + a[i]) / 2;
209 if (lmax && middle < seqlen[i] &&
210 comp(begin_seqs[i].first[middle], *lmax))
211 a[i] =
std::min(a[i] + n + 1, seqlen[i]);
216 diff_type leftsize = 0;
217 for (diff_type i = 0; i < m; ++i)
218 leftsize += a[i] / (n + 1);
220 diff_type skew = rank / (n + 1) - leftsize;
226 SamplePair, std::vector<SamplePair>,
227 lexicographic_rev<ValueType, diff_type, Comparator> >
230 for (diff_type i = 0; i < m; ++i) {
231 if (b[i] < seqlen[i])
232 pq.push(SamplePair(begin_seqs[i].first[b[i]], i));
235 for ( ; skew != 0 && !pq.empty(); --skew)
237 diff_type src = pq.top().second;
240 a[src] =
std::min(a[src] + n + 1, seqlen[src]);
243 if (b[src] < seqlen[src])
244 pq.push(SamplePair(begin_seqs[src].first[b[src]], src));
251 SamplePair, std::vector<SamplePair>,
252 lexicographic<ValueType, diff_type, Comparator> >
255 for (diff_type i = 0; i < m; ++i) {
257 pq.push(SamplePair(begin_seqs[i].first[a[i] - 1], i));
260 for ( ; skew != 0; ++skew)
262 diff_type src = pq.top().second;
269 pq.push(SamplePair(begin_seqs[src].first[a[src] - 1], src));
281 ValueType* maxleft =
nullptr, * minright =
nullptr;
282 for (diff_type i = 0; i < m; ++i)
288 maxleft = &(begin_seqs[i].first[a[i] - 1]);
293 if (comp(*maxleft, begin_seqs[i].first[a[i] - 1]))
294 maxleft = &(begin_seqs[i].first[a[i] - 1]);
297 if (b[i] < seqlen[i])
301 minright = &(begin_seqs[i].first[b[i]]);
306 if (comp(begin_seqs[i].first[b[i]], *minright))
307 minright = &(begin_seqs[i].first[b[i]]);
314 if (!maxleft || comp(*minright, *maxleft))
324 for (diff_type i = 0; i < m; ++i)
326 diff_type lb = std::lower_bound(
327 begin_seqs[i].first, begin_seqs[i].first + seqlen[i],
328 *minright, comp) - begin_seqs[i].first;
340 #endif // !TLX_ALGORITHM_MULTISEQUENCE_SELECTION_HEADER Compare a pair of types lexicographically, ascending.
static uint_pair max()
return an uint_pair instance containing the largest value possible
Simpler non-growing vector without initialization.
ValueType multisequence_selection(const RanSeqs &begin_seqs, const RanSeqs &end_seqs, const RankType &rank, RankType &offset, Comparator comp=Comparator())
Selects the element at a certain global rank from several sorted sequences.
bool operator()(const std::pair< T1, T2 > &p1, const std::pair< T1, T2 > &p2)
lexicographic(Comparator &comp)
lexicographic_rev(Comparator &comp)
Compare a pair of types lexicographically, descending.
static uint_pair min()
return an uint_pair instance containing the smallest value possible
static int round_up_to_power_of_two(int i)
does what it says: round up to next power of two