Euphoria
multisort.h
Go to the documentation of this file.
1 #pragma once
2 
3 
4 
5 
6 #include <numeric>
7 #include <algorithm>
8 #include <memory>
9 
10 #include "core/quicksort.h"
11 #include "core/insertionsort.h"
12 
13 namespace eu::core
14 {
15  enum class SortStyle
16  {
17  ascending,
19  };
20 
21  template <typename T>
22  struct Sortable
23  {
24  Sortable() = default;
25  virtual ~Sortable() = default;
26 
27  Sortable(const Sortable<T>&) = delete;
28  Sortable(Sortable<T>&&) = delete;
29  void operator=(const Sortable<T>&) = delete;
30  void operator=(Sortable<T>&&) = delete;
31 
32  virtual int sort(const T& lhs, const T& rhs) = 0;
33  };
34 
35  template <typename T>
36  using SortableList = std::vector<std::shared_ptr<Sortable<T>>>;
37 
38  template <typename T, typename TValue, typename TSortFunc>
39  struct SortAction : public Sortable<T>
40  {
41  TValue T::*member;
43  TSortFunc sort_func;
44 
45  SortAction(TValue T::*m, core::SortStyle s, TSortFunc f)
47  {}
48 
49  int
50  sort(const T& lhs, const T& rhs) override
51  {
52  const int result = sort_func(lhs.*member, rhs.*member);
53  return sort_style == SortStyle::ascending ? result : -result;
54  }
55  };
56 
57  template <typename T>
58  int
59  sort_using_less(T lhs, T rhs)
60  {
61  if(lhs == rhs)
62  {
63  return 0;
64  }
65  return lhs < rhs ? 1 : -1;
66  }
67 
68  // todo(Gustav): refactor away crtp and inheritence?
69 
73  template <typename T, typename TSelf>
74  struct SortBuilder
75  {
77  bool stable_sort = false;
78 
79  template <typename TSortFunc, typename TValue>
80  TSelf&
82  (
83  TValue T::*member,
84  TSortFunc sort_func,
85  SortStyle sort_style = SortStyle::ascending
86  )
87  {
88  auto o = std::make_shared<SortAction<T, TValue, TSortFunc>>
89  (
90  member, sort_style, sort_func
91  );
92  sort_order.emplace_back(o);
93  return static_cast<TSelf&>(*this);
94  }
95 
96  template <typename TValue>
97  TSelf&
98  sort(TValue T::*member, SortStyle sort_style = SortStyle::ascending)
99  {
100  return sort(member, &sort_using_less<TValue>, sort_style);
101  }
102 
103  TSelf&
105  {
106  stable_sort = true;
107  return *this;
108  }
109  };
110 
111  template <typename T, typename TSelf>
112  std::vector<size_t>
114  (
115  const std::vector<T>& data,
116  const SortBuilder<T, TSelf>& builder
117  )
118  {
119  std::vector<size_t> r(data.size());
120  std::iota(std::begin(r), std::end(r), 0);
121 
122  if(builder.sort_order.empty())
123  {
124  return r;
125  }
126 
127  const auto sort_function = [&data, &builder](size_t lhs, size_t rhs) -> int
128  {
129  for(const auto& so: builder.sort_order)
130  {
131  const auto result = so->sort(data[lhs], data[rhs]);
132  if(result != 0)
133  {
134  return -result;
135  }
136  }
137  return 0;
138  };
139 
140  // is a stable sort is requested, use insertion sort, otherwise use the faster quick sort
141  if(builder.stable_sort)
142  {
143  do_inplace_insertion_sort(&r, sort_function);
144  }
145  else
146  {
147  do_inplace_quick_sort(&r, sort_function);
148  }
149 
150  return r;
151  }
152 
153 }
154 
int sort_using_less(T lhs, T rhs)
Definition: multisort.h:59
std::vector< size_t > get_sorted_indices(const std::vector< T > &data, const SortBuilder< T, TSelf > &builder)
Definition: multisort.h:114
std::vector< std::shared_ptr< Sortable< T > >> SortableList
Definition: multisort.h:36
void do_inplace_quick_sort(std::vector< T > *array, TSortFunc sort_func)
Definition: quicksort.h:55
void do_inplace_insertion_sort(std::vector< T > *pointer_to_array, TSortFunc sort_func)
Definition: insertionsort.h:10
TSortFunc sort_func
Definition: multisort.h:43
SortAction(TValue T::*m, core::SortStyle s, TSortFunc f)
Definition: multisort.h:45
core::SortStyle sort_style
Definition: multisort.h:42
int sort(const T &lhs, const T &rhs) override
Definition: multisort.h:50
TValue T::* member
Definition: multisort.h:41
TSelf & sort(TValue T::*member, SortStyle sort_style=SortStyle::ascending)
Definition: multisort.h:98
TSelf & sort(TValue T::*member, TSortFunc sort_func, SortStyle sort_style=SortStyle::ascending)
Definition: multisort.h:82
TSelf & use_stable_sort()
Definition: multisort.h:104
SortableList< T > sort_order
Definition: multisort.h:76
Sortable(const Sortable< T > &)=delete
void operator=(Sortable< T > &&)=delete
virtual ~Sortable()=default
void operator=(const Sortable< T > &)=delete
virtual int sort(const T &lhs, const T &rhs)=0
Sortable(Sortable< T > &&)=delete