NCBI C++ ToolKit
ctsort_cxx14.hpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 #ifndef __CTSORT_CXX14_HPP_INCLUDED__
2 #define __CTSORT_CXX14_HPP_INCLUDED__
3 
4 /* $Id: ctsort_cxx14.hpp 98673 2022-12-19 16:02:19Z gotvyans $
5  * ===========================================================================
6  *
7  * PUBLIC DOMAIN NOTICE
8  * National Center for Biotechnology Information
9  *
10  * This software/database is a "United States Government Work" under the
11  * terms of the United States Copyright Act. It was written as part of
12  * the author's official duties as a United States Government employee and
13  * thus cannot be copyrighted. This software/database is freely available
14  * to the public for use. The National Library of Medicine and the U.S.
15  * Government have not placed any restriction on its use or reproduction.
16  *
17  * Although all reasonable efforts have been taken to ensure the accuracy
18  * and reliability of the software and data, the NLM and the U.S.
19  * Government do not and cannot warrant the performance or results that
20  * may be obtained by using this software or data. The NLM and the U.S.
21  * Government disclaim all warranties, express or implied, including
22  * warranties of performance, merchantability or fitness for any particular
23  * purpose.
24  *
25  * Please cite the author in any work or product based on this material.
26  *
27  * ===========================================================================
28  *
29  * Authors: Sergiy Gotvyanskyy
30  *
31  * File Description:
32  *
33  * compile time sorting algorithm
34  *
35  *
36  */
37 
38 #include <type_traits>
39 #include <utility>
40 #include <tuple>
41 #include <limits>
42 
43 namespace compile_time_bits
44 {
45 
46  // compile time sort algorithm
47  // uses insertion sort https://en.wikipedia.org/wiki/Insertion_sort
48  template<typename _Traits, typename _AllowDuplicates>
50  {
51  public:
52  using size_type = std::size_t;
53  using sort_traits = _Traits;
55  using hash_type = typename sort_traits::hash_type;
56  using init_type = typename sort_traits::init_type;
57 
58  static constexpr bool remove_duplicates = !_AllowDuplicates::value;
59  static constexpr bool can_index =
60  std::numeric_limits<hash_type>::is_integer ||
62 
63  using tag_can_index = std::integral_constant<bool, can_index>;
64 
65  template<typename _Init>
66  static constexpr auto sort(_Init&& init) noexcept
67  {
68  return x_sort(tag_can_index{}, init);
69  }
70 
71  template<bool _SortByValues, typename _Init>
72  static constexpr auto sort(std::integral_constant<bool, _SortByValues> _Tag, _Init&& init) noexcept
73  {
74  return x_sort(_Tag, init);
75  }
76 
77  template<typename _Init>
78  static constexpr auto make_indices(_Init&& input) noexcept
79  { // this will produce the index of elements sorted by rules provided in sort_traits
81  auto real_size = insert_sort_indices(indices, input);
82  return std::make_pair(real_size, indices);
83  }
84 
85  protected:
86 
87  struct Less
88  {
89  template<typename _Input>
90  constexpr bool operator()(const _Input& input, size_t l, size_t r) const
91  {
92  return typename sort_traits::hashed_key_type::hash_compare{}(
93  sort_traits::get_init_hash(input[l]),
94  sort_traits::get_init_hash(input[r])
95  );
96  }
97  };
98 
100  static constexpr auto x_sort(tag_SortByHashes, const _Init& init) noexcept
101  { // sort by hashes, return tuple( real_size, sorted_values, sorted_indices)
102  auto indices = make_indices(init);
103  auto hashes = construct_hashes(init, indices, std::make_index_sequence<N>{});
104  auto values = construct_values(init, indices, std::make_index_sequence<N>{});
105  return std::make_tuple(indices.first, values, hashes);
106  }
107 
109  static constexpr auto x_sort(tag_SortByValues, const _Init& init) noexcept
110  { // sort by values, return pair( real_size, sorted_values)
111  auto indices = make_indices(init);
112  auto values = construct_values(init, indices, std::make_index_sequence<N>{});
113  return std::make_pair(indices.first, values);
114  }
115 
116  template<typename _Indices>
117  static constexpr void insert_down(_Indices& indices, size_type head, size_type tail, size_type current)
118  {
119  while (head != tail)
120  {
121  auto prev = tail--;
122  indices[prev] = indices[tail];
123  }
124  indices[head] = current;
125  }
126  template<typename _Indices, typename _Input, typename _Pred>
127  static constexpr size_type const_lower_bound(_Pred pred, const _Indices& indices, const _Input& input, size_type size, size_type value)
128  {
129  size_type _UFirst = 0;
130  size_type _Count = size;
131 
132  while (0 < _Count)
133  { // divide and conquer, find half that contains answer
134  const size_type _Count2 = _Count >> 1; // TRANSITION, VSO#433486
135  const size_type _UMid = _UFirst + _Count2;
136  if (pred(input, indices[_UMid], value))
137  { // try top half
138  _UFirst = (_UMid + 1); // _Next_iter(_UMid);
139  _Count -= _Count2 + 1;
140  }
141  else
142  {
143  _Count = _Count2;
144  }
145  }
146 
147  return _UFirst;
148  }
149  template<typename _Indices, typename _Input, typename _Pred>
150  static constexpr size_type const_upper_bound(_Pred pred, const _Indices& indices, const _Input& input, size_type size, size_type value)
151  {
152  size_type _UFirst = 0;
153  size_type _Count = size;
154 
155  while (0 < _Count)
156  { // divide and conquer, find half that contains answer
157  const size_type _Count2 = _Count >> 1; // TRANSITION, VSO#433486
158  const size_type _UMid = _UFirst + _Count2;
159  if (pred(input, value, indices[_UMid]))
160  {
161  _Count = _Count2;
162  }
163  else
164  { // try top half
165  _UFirst = (_UMid + 1); // _Next_iter(_UMid);
166  _Count -= _Count2 + 1;
167  }
168  }
169 
170  return (_UFirst);
171  }
172 
173  template<typename _Indices, typename _Input>
174  static constexpr size_type insert_sort_indices(_Indices& result, const _Input& input)
175  {
176  Less pred{};
177  const auto size = result.size();
178  if (size < 2)
179  return size;
180 
181  // current is the first element of the unsorted part of the array
182  size_type current = 0;
183  // the last inserted element into sorted part of the array
184  size_type last = current;
185  result[0] = 0;
186  current++;
187 
188  while (current != size)
189  {
190  if (pred(input, result[last], current))
191  {// optimization for presorted arrays
192  result[++last] = current;
193  }
194  else {
195  // we may exclude last element since it's already known as smaller then current
196  // using const_upper_bound helps to preserve the order of rows with identical values (or their hashes)
197  // using const_lower_bound will reverse that order
198  auto fit = const_upper_bound(pred, result, input, last, current);
199  bool need_to_move = !remove_duplicates;
200  if (remove_duplicates)
201  {
202  need_to_move = (fit == 0) || pred(input, result[fit-1], current);
203  }
204  if (need_to_move)
205  {
206  ++last;
207  insert_down(result, fit, last, current);
208  }
209  }
210  ++current;
211  }
212  if (remove_duplicates)
213  {// fill the rest of the indices with maximum value
214  current = last;
215  while (++current != size)
216  {
217  result[current] = result[last];
218  }
219  }
220  return 1 + last;
221  }
222 
223  template<typename _Input, typename _Indices, size_type... I>
224  static constexpr auto construct_hashes(const _Input& input, const _Indices& indices, std::index_sequence<I...>) noexcept
225  -> const_array<hash_type, sizeof...(I)>
226  { // only 'realsize' elements are collected, the leftover is padded with the last element
227  size_type real_size = indices.first;
228  return { sort_traits::get_init_hash(input[indices.second[I < real_size ? I : real_size - 1]]) ...};
229  }
230 
231  template<typename _Input, typename _Indices, size_type... I>
232  static constexpr auto construct_values(const _Input& input, const _Indices& indices, std::index_sequence<I...>) noexcept
233  -> const_array<value_type, sizeof...(I)>
234  { // only 'realsize' elements are collected, the leftover is padded with the last element
235  auto real_size = indices.first;
236  return { sort_traits::construct(input[indices.second[I < real_size ? I : real_size - 1]]) ...};
237  }
238  };
239 }
240 
241 #endif
static constexpr void insert_down(_Indices &indices, size_type head, size_type tail, size_type current)
static constexpr auto make_indices(_Init &&input) noexcept
static constexpr auto x_sort(tag_SortByHashes, const _Init &init) noexcept
static constexpr size_type const_lower_bound(_Pred pred, const _Indices &indices, const _Input &input, size_type size, size_type value)
static constexpr size_type insert_sort_indices(_Indices &result, const _Input &input)
static constexpr auto sort(_Init &&init) noexcept
static constexpr auto construct_values(const _Input &input, const _Indices &indices, std::index_sequence< I... >) noexcept -> const_array< value_type, sizeof...(I)>
typename sort_traits::init_type init_type
static constexpr auto x_sort(tag_SortByValues, const _Init &init) noexcept
static constexpr auto construct_hashes(const _Input &input, const _Indices &indices, std::index_sequence< I... >) noexcept -> const_array< hash_type, sizeof...(I)>
static constexpr size_type const_upper_bound(_Pred pred, const _Indices &indices, const _Input &input, size_type size, size_type value)
typename sort_traits::value_type value_type
static constexpr bool remove_duplicates
static constexpr bool can_index
typename sort_traits::hash_type hash_type
static constexpr auto sort(std::integral_constant< bool, _SortByValues > _Tag, _Init &&init) noexcept
std::integral_constant< bool, can_index > tag_can_index
char value[7]
Definition: config.c:431
#define head
Definition: ct_nlmzip_i.h:138
static void DLIST_NAME() init(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:40
static DLIST_TYPE *DLIST_NAME() last(DLIST_LIST_TYPE *list)
Definition: dlist.tmpl.h:51
static DLIST_TYPE *DLIST_NAME() prev(DLIST_LIST_TYPE *list, DLIST_TYPE *item)
Definition: dlist.tmpl.h:61
static int input()
std::false_type tag_SortByValues
std::true_type tag_SortByHashes
double value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:228
const struct ncbi::grid::netcache::search::fields::SIZE size
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
constexpr bool operator()(const _Input &input, size_t l, size_t r) const
else result
Definition: token2.c:20
Modified on Wed Dec 06 07:12:23 2023 by modify_doxy.py rev. 669887