LAL: Linear Arrangement Library 24.10.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
counting_sort.hpp
1/*********************************************************************
2 *
3 * Linear Arrangement Library - A library that implements a collection
4 * algorithms for linear arrangments of graphs.
5 *
6 * Copyright (C) 2019 - 2024
7 *
8 * This file is part of Linear Arrangement Library. The full code is available
9 * at:
10 * https://github.com/LAL-project/linear-arrangement-library.git
11 *
12 * Linear Arrangement Library is free software: you can redistribute it
13 * and/or modify it under the terms of the GNU Affero General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * Linear Arrangement Library is distributed in the hope that it will be
18 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with Linear Arrangement Library. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * Contact:
26 *
27 * LluĂ­s Alemany Puig (lluis.alemany.puig@upc.edu)
28 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
29 * CQL (Complexity and Quantitative Linguistics Lab)
30 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
31 * Webpage: https://cqllab.upc.edu/people/lalemany/
32 *
33 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
34 * LQMC (Quantitative, Mathematical, and Computational Linguisitcs)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office 220, Omega building
37 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
38 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
39 *
40 ********************************************************************/
41
42#pragma once
43
44// C++ includes
45#include <functional>
46#include <tuple>
47
48// lal includes
49#include <lal/detail/array.hpp>
50#include <lal/detail/type_traits/is_pointer_iterator.hpp>
51#include <lal/detail/sorting/sorting_types.hpp>
52
53namespace lal {
54namespace detail {
55namespace sorting {
56
63namespace countingsort {
64
71template <typename T>
72struct memory {
77
79 memory() noexcept = default;
81 memory(const memory&) noexcept = default;
83 memory(memory&&) noexcept = default;
85 memory& operator= (const memory&) noexcept = default;
87 memory& operator= (memory&&) noexcept = default;
88
97 memory(const std::size_t largest_key_plus_1, const std::size_t max_size_container)
98 noexcept
99 : count(largest_key_plus_1, 0),
100 output(max_size_container)
101 { }
102
104 ~memory() noexcept = default;
105
107 void reset_count() noexcept { count.fill(0); }
108};
109
110} // -- namespace countingsort
111
143template <
144 typename value_t,
145 sort_type type,
146 bool memory_has_frequencies,
147 // Can be inferred \/ ...
148 typename value_iterator_t,
149 typename Callable,
150 std::enable_if_t< is_pointer_iterator_v<value_t, value_iterator_t>, bool > = true
151>
153 const value_iterator_t begin, const value_iterator_t end,
154 const std::size_t largest_key_plus_1,
155 const Callable& key,
157)
158noexcept
159{
160 // ensure the 'key' function is correct
161 static_assert(
162 std::is_constructible_v<
163 std::function<std::size_t (const value_t&)>,
164 Callable
165 >
166 );
167
168 if (begin == end) { return; }
169
170 if constexpr (not memory_has_frequencies) {
171 // calculate frequency of each element
172 for (auto it = begin; it != end; ) {
173 // get the key of the element into a variable so that
174 // the function is NOT called more than once per iteration
175 const std::size_t elem_key = key(*(it++));
176
177 ++mem.count[elem_key];
178 }
179 }
180
181 std::size_t total = 0;
182 for (std::size_t k = 0; k < largest_key_plus_1; ++k) {
183 std::tie(mem.count[k], total)
184 = std::make_pair(total, mem.count[k] + total);
185 }
186
187 std::size_t actual_container_size = 0;
188 for (auto it = begin; it != end; ) {
189 ++actual_container_size;
190
191 // get the key of the element into a variable so that
192 // the function is NOT called more than once per iteration
193 const std::size_t elem_key = key(*it);
194
195 mem.output[mem.count[elem_key]] = std::move(*(it++));
196 ++mem.count[elem_key];
197 }
198
199 // calculate output
200 if constexpr (type == sort_type::non_decreasing) {
201 auto it = begin;
202 for (std::size_t k = 0; k < actual_container_size;) {
203 *(it++) = std::move(mem.output[k++]);
204 }
205 }
206 else {
207 auto it = begin;
208 for (std::size_t k = actual_container_size - 1; k > 0;) {
209 *(it++) = std::move(mem.output[k--]);
210 }
211 *it = std::move(mem.output[0]);
212 }
213}
214
244template <
245 typename value_t,
246 sort_type type,
247 typename value_iterator_t,
248 // Can be inferred \/ ...
249 typename Callable,
250 std::enable_if_t< is_pointer_iterator_v<value_t, value_iterator_t>, bool > = true
251>
253 const value_iterator_t begin, const value_iterator_t end,
254 const std::size_t largest_key,
255 const std::size_t upper_bound_size,
256 const Callable& key
257)
258noexcept
259{
260 // ensure the 'key' function is correct
261 static_assert(
262 std::is_constructible_v<
263 std::function<std::size_t (const value_t&)>,
264 Callable
265 >
266 );
267
268 // nothing to do if there are no elements to sort
269 if (begin == end) { return; }
270
271 countingsort::memory<value_t> mem(largest_key+1, upper_bound_size);
272
274 (begin, end, largest_key+1, key, mem);
275}
276
277} // -- namespace sorting
278} // -- namespace detail
279} // -- namespace lal
sort_type
The different types of sorting patterns.
Definition sorting_types.hpp:49
@ non_decreasing
Non-decreasing sort type.
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const Callable &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition counting_sort.hpp:152
Main namespace of the library.
Definition basic_types.hpp:48
Wrapper of a C array for automatic deallocation of memory.
Definition array.hpp:59
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition array.hpp:272
Memory used for the counting sort algorithm.
Definition counting_sort.hpp:72
void reset_count() noexcept
Set the count member to 0.
Definition counting_sort.hpp:107
array< std::size_t > count
Amount of times the key of an element occurs.
Definition counting_sort.hpp:74
~memory() noexcept=default
Destructor.
array< T > output
The output array.
Definition counting_sort.hpp:76
memory() noexcept=default
Constructor.