Geogram Version 1.9.6-rc
A programming library of geometric algorithms
Loading...
Searching...
No Matches
permutation.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40#ifndef GEOGRAM_BASIC_PERMUTATION
41#define GEOGRAM_BASIC_PERMUTATION
42
46
52namespace GEO {
53
57 namespace Permutation {
58
62 constexpr index_t MARKED_BIT = index_t(1) << (sizeof(index_t)*8 - 1);
63
68
80 inline bool is_valid(const vector<index_t>& permutation) {
81 std::vector<bool> visited(permutation.size(), false);
82 for(index_t i = 0; i < permutation.size(); i++) {
83 if(permutation[i] >= permutation.size()) {
84 return false;
85 }
86 if(visited[permutation[i]]) {
87 return false;
88 }
89 visited[permutation[i]] = true;
90 }
91 return true;
92 }
93
105 inline void mark(vector<index_t>& permutation, index_t i) {
106 geo_debug_assert(i < permutation.size());
107 permutation[i] |= MARKED_BIT;
108 }
109
116 inline bool is_marked(const vector<index_t>& permutation, index_t i) {
117 geo_debug_assert(i < permutation.size());
118 return ((permutation[i] & MARKED_BIT) != 0);
119 }
120
129 inline void unmark(vector<index_t>& permutation, index_t i) {
130 geo_debug_assert(is_marked(permutation, i));
131 permutation[i] &= ~MARKED_BIT;
132 }
133
157 inline void apply(
158 void* data, const vector<index_t>& permutation_in,
159 size_t elemsize
160 ) {
161 geo_debug_assert(permutation_in.size() <= MAX_SIZE);
162 Memory::pointer pdata = (Memory::pointer) (data);
163 vector<index_t>& permutation =
164 const_cast<vector<index_t>&>(permutation_in);
165 geo_debug_assert(is_valid(permutation));
166 Memory::byte* temp = static_cast<Memory::byte*>(alloca(elemsize));
167 for(index_t k = 0; k < permutation.size(); k++) {
168 if(is_marked(permutation, k)) {
169 continue;
170 }
171 index_t i = k;
172 index_t j = permutation[k];
173 Memory::copy(temp, pdata + i * elemsize, elemsize);
174 mark(permutation, k);
175 while(j != k) {
177 pdata + i * elemsize, pdata + j * elemsize, elemsize
178 );
179 index_t nj = permutation[j];
180 mark(permutation, j);
181 i = j;
182 j = nj;
183 }
184 Memory::copy(pdata + i * elemsize, temp, elemsize);
185 }
186 for(index_t k = 0; k < permutation.size(); k++) {
187 unmark(permutation, k);
188 }
189 }
190
211 template <class T>
212 inline void apply(
213 vector<T>& data, const vector<index_t>& permutation_in
214 ) {
215 geo_debug_assert(permutation_in.size() <= MAX_SIZE);
216 vector<index_t>& permutation =
217 const_cast<vector<index_t>&>(permutation_in);
218 geo_debug_assert(is_valid(permutation));
219 T temp;
220 for(index_t k = 0; k < permutation.size(); k++) {
221 if(is_marked(permutation, k)) {
222 continue;
223 }
224 index_t i = k;
225 temp = data[i];
226 index_t j = permutation[k];
227 mark(permutation, k);
228 while(j != k) {
229 data[i] = data[j];
230 index_t nj = permutation[j];
231 mark(permutation, j);
232 i = j;
233 j = nj;
234 }
235 data[i] = temp;
236 }
237 for(index_t k = 0; k < permutation.size(); k++) {
238 unmark(permutation, k);
239 }
240 }
241
255 inline void invert(vector<index_t>& permutation) {
256 geo_debug_assert(permutation.size() < MAX_SIZE);
257 geo_debug_assert(is_valid(permutation));
258 for(index_t k = 0; k < permutation.size(); k++) {
259 if(is_marked(permutation, k)) {
260 continue;
261 }
262 index_t i = k;
263 index_t j = permutation[i];
264 while(j != k) {
265 index_t temp = permutation[j];
266 permutation[j] = i;
267 mark(permutation, j);
268 i = j;
269 j = temp;
270 }
271 permutation[j] = i;
272 mark(permutation, j);
273 }
274 for(index_t k = 0; k < permutation.size(); k++) {
275 unmark(permutation, k);
276 }
277 }
278
288 inline void invert(
289 const vector<index_t>& permutation, vector<index_t>& invert
290 ) {
291 geo_debug_assert(is_valid(permutation));
292 invert.resize(permutation.size());
293 for(index_t i=0; i<permutation.size(); ++i) {
294 invert[permutation[i]] = i;
295 }
296 }
297
298 }
299}
300
301#endif
#define geo_debug_assert(x)
Verifies that a condition is met.
Definition assert.h:196
Vector with aligned memory allocation.
Definition memory.h:660
index_t size() const
Gets the number of elements.
Definition memory.h:706
Common include file, providing basic definitions. Should be included before anything else by all head...
Types and functions for memory manipulation.
unsigned char byte
Unsigned byte type.
Definition memory.h:92
byte * pointer
Pointer to unsigned byte(s)
Definition memory.h:104
void copy(void *to, const void *from, size_t size)
Copies a memory block.
Definition memory.h:129
bool is_marked(const vector< index_t > &permutation, index_t i)
Checks if a permutation element has been visited.
constexpr index_t MAX_SIZE
Maximum size of a permutation that can be applied in-place.
Definition permutation.h:67
void unmark(vector< index_t > &permutation, index_t i)
Unmarks a permutation element.
void mark(vector< index_t > &permutation, index_t i)
Marks a permutation element as visited.
constexpr index_t MARKED_BIT
Mark used to mark elements for in-place permutation.
Definition permutation.h:62
void invert(vector< index_t > &permutation)
Inverts a permutation in-place.
bool is_valid(const vector< index_t > &permutation)
Checks whether a vector is a valid permutation.
Definition permutation.h:80
void apply(void *data, const vector< index_t > &permutation_in, size_t elemsize)
Applies a permutation in-place. Permutes the first N elements of size elemsize in array data using pe...
Global Vorpaline namespace.
Definition basic.h:55
geo_index_t index_t
The type for storing and manipulating indices.
Definition numeric.h:329
Types and functions for numbers manipulation.