@@ -37,22 +37,71 @@ behavior (usually a core dump).
3737
3838#include < algorithm>
3939#include < iterator>
40+ #include < numeric>
41+ #include < type_traits>
4042#include < vector>
4143
42- #include < type_traits>
43- #include " boost/concept_check.hpp"
44+ #include < boost/concept_check.hpp>
4445
46+ #include " DataFormats/Common/interface/BoolCache.h"
4547#include " DataFormats/Common/interface/CMS_CLASS_VERSION.h"
4648#include " DataFormats/Common/interface/DetSet.h"
4749#include " DataFormats/Common/interface/FillView.h"
4850#include " DataFormats/Common/interface/Ref.h"
4951#include " DataFormats/Common/interface/traits.h"
50-
5152#include " FWCore/Utilities/interface/EDMException.h"
5253
53- #include " DataFormats/Common/interface/BoolCache.h"
54-
5554namespace edm {
55+
56+ namespace detail {
57+
58+ // from https://devblogs.microsoft.com/oldnewthing/20170104-00/?p=95115
59+
60+ template <typename Iter1, typename Iter2>
61+ void apply_permutation (Iter1 first, Iter1 last, Iter2 indices) {
62+ using T = std::iterator_traits<Iter1>::value_type;
63+ using Diff = std::iterator_traits<Iter2>::value_type;
64+ Diff length = last - first;
65+ for (Diff i = 0 ; i < length; i++) {
66+ Diff current = i;
67+ if (i != indices[current]) {
68+ T t{std::move (first[i])};
69+ while (i != indices[current]) {
70+ Diff next = indices[current];
71+ first[current] = std::move (first[next]);
72+ indices[current] = current;
73+ current = next;
74+ }
75+ first[current] = std::move (t);
76+ indices[current] = current;
77+ }
78+ }
79+ }
80+
81+ // from https://devblogs.microsoft.com/oldnewthing/20170106-00/?p=95135
82+
83+ template <typename Iter, typename UnaryOperation, typename Compare>
84+ void sort_by_key (Iter first, Iter last, UnaryOperation op, Compare comp) {
85+ using Diff = std::iterator_traits<Iter>::difference_type;
86+ using T = std::iterator_traits<Iter>::value_type;
87+ using Key = decltype (op (std::declval<T>()));
88+ Diff length = std::distance (first, last);
89+ std::vector<Key> keys;
90+ keys.reserve (length);
91+ std::transform (first, last, std::back_inserter (keys), [&](T& t) { return op (t); });
92+ std::vector<Diff> indices (length);
93+ std::iota (indices.begin (), indices.end (), static_cast <Diff>(0 ));
94+ std::sort (indices.begin (), indices.end (), [&](Diff a, Diff b) { return comp (keys[a], keys[b]); });
95+ apply_permutation (first, last, indices.begin ());
96+ }
97+
98+ template <typename Iter, typename UnaryOperation>
99+ void sort_by_key (Iter first, Iter last, UnaryOperation op) {
100+ sort_by_key (first, last, op, std::less<>());
101+ }
102+
103+ } // namespace detail
104+
56105 class ProductID ;
57106
58107 // ------------------------------------------------------------
@@ -340,7 +389,11 @@ namespace edm {
340389 for (; i != e; ++i) {
341390 i->data .shrink_to_fit ();
342391 // sort the Detset pointed to by
343- std::sort (i->data .begin (), i->data .end ());
392+ if constexpr (requires (const T& t) { t.sort_key (); }) {
393+ edm::detail::sort_by_key (i->data .begin (), i->data .end (), [](const T& t) { return t.sort_key (); });
394+ } else {
395+ std::sort (i->data .begin (), i->data .end ());
396+ }
344397 }
345398 }
346399
0 commit comments