P99
p99_uf.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the author and copyright holder for this work is */
5 /* (C) copyright 2016 Jens Gustedt, INRIA, France */
6 /* */
7 /* This file is free software; it is part of the P99 project. */
8 /* */
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
12 /* */
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
14 /* */
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
20 /* */
21 #ifndef P99_UF_H
22 #define P99_UF_H
23 
24 #include "p99_compiler.h"
25 #include "p99_type.h"
26 #include "p99_c99.h"
27 
54 
55 struct p99_uf {
56  uint64_t size;
57  int64_t tab[];
58 };
59 
65 p99_uf* p99_uf_init(p99_uf* uf, uint64_t size) {
66  if (uf) {
67  *uf = (p99_uf) { .size = size, };
68  memset(uf->tab, UCHAR_MAX, sizeof(int64_t[size]));
69  }
70  return uf;
71 }
72 
74 void p99_uf_destroy(p99_uf const volatile* uf) {
75  // empty
76 }
77 
85 p99_uf* p99_uf_alloc(uint64_t size) {
86  return p99_uf_init(malloc(sizeof(int64_t[size])+offsetof(p99_uf, tab)), size);
87 }
88 
93 void p99_uf_free(p99_uf const volatile* uf) {
94  p99_uf_destroy(uf);
95  free((void*)uf);
96 }
97 
99 bool p00_uf_root(int64_t pos, int64_t const tab[static pos+1]) {
100  return tab[pos] < 0;
101 }
102 
104 uint64_t p00_uf_size(int64_t pos, int64_t const tab[static pos+1]) {
105  return p00_uf_root(pos, tab) ? -tab[pos] : 0;
106 }
107 
109 int64_t p00_uf_find(int64_t pos, int64_t const tab[static pos+1]) {
110  while (!p00_uf_root(pos, tab)) pos = tab[pos];
111  return pos;
112 }
113 
115 int64_t p99_uf_find(p99_uf const* uf, uint64_t pos) {
116  if (!uf || (uf->size <= pos)) return -1;
117  else return p00_uf_find(pos, uf->tab);
118 }
119 
121 int64_t p00_uf_exchange(int64_t pos, int64_t tab[static pos+1], int64_t val) {
122  int64_t ret = tab[pos];
123  tab[pos] = val;
124  return ret;
125 }
126 
128 void p00_uf_compress(uint64_t pos, int64_t tab[static pos+1], uint64_t root) {
129  while (!p00_uf_root(pos, tab)) {
130  pos = p00_uf_exchange(pos, tab, root);
131  }
132 }
133 
135 int64_t p00_uf_findCompress(int64_t pos, int64_t tab[static pos+1]) {
136  int64_t root = p00_uf_find(pos, tab);
137  p00_uf_compress(pos, tab, root);
138  return root;
139 }
140 
142 int64_t p99_uf_findCompress(p99_uf* uf, uint64_t pos) {
143  if (!uf || (uf->size <= pos)) return -1;
144  return p00_uf_findCompress(pos, uf->tab);
145 }
146 
148 uint64_t p99_uf_size(p99_uf* uf, uint64_t pos) {
149  if (uf || (uf->size > pos)) {
150  int64_t root = p00_uf_findCompress(pos, uf->tab);
151  if (root >= 0 && p00_uf_root(root, uf->tab))
152  return -uf->tab[root];
153  }
154  return 0;
155 }
156 
158 void p00_uf_union(int64_t left, int64_t right, int64_t tab[static (left < right ? right : left)+1]) {
159  tab[left] += p00_uf_exchange(right, tab, left);
160 }
161 
163 int64_t p99_uf_union(p99_uf* uf, uint64_t left, uint64_t right) {
164  int64_t root = -1;
165  if (uf && (uf->size > left) && (uf->size > right)) {
166  root = p00_uf_findCompress(left, uf->tab);
167  if (root >= 0) {
168  int64_t rright = p00_uf_find(right, uf->tab);
169  if (rright >= 0) {
170  // use the new root to mark all elements of the right
171  p00_uf_compress(right, uf->tab, root);
172  // now also link the old root on the right to the new one
173  p00_uf_union(root, rright, uf->tab);
174  } else
175  root = rright;
176  }
177  }
178  return root;
179 }
180 
182 void p99_uf_flatten(p99_uf* uf, uint64_t pos, uint64_t length) {
183  if (uf && (uf->size > pos) && ((uf->size-pos) >= length)) {
184  for (uint64_t stop = pos+length; pos < stop; ++pos) {
185  p00_uf_findCompress(pos, uf->tab);
186  }
187  }
188 }
189 
190 #endif
p99_uf::tab
int64_t tab[]
Definition: p99_uf.h:57
p99_uf_free
void p99_uf_free(p99_uf const volatile *uf)
Free a UF data structure.
Definition: p99_uf.h:93
p99_uf_size
uint64_t p99_uf_size(p99_uf *uf, uint64_t pos)
Definition: p99_uf.h:148
p99_c99.h
C99 specific include files that are required by the standard.
p99_uf_flatten
void p99_uf_flatten(p99_uf *uf, uint64_t pos, uint64_t length)
Definition: p99_uf.h:182
p99_type.h
p99_compiler.h
Group compiler dependencies together in one file.
p99_uf_init
p99_uf * p99_uf_init(p99_uf *uf, uint64_t size)
Initialize the UF data structure to all singletons, that is everybody is root and the size of the set...
Definition: p99_uf.h:65
p99_uf::size
uint64_t size
Definition: p99_uf.h:56
p99_uf_findCompress
int64_t p99_uf_findCompress(p99_uf *uf, uint64_t pos)
Definition: p99_uf.h:142
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
p99_uf_alloc
p99_uf * p99_uf_alloc(uint64_t size)
Allocate an new UF data structure.
Definition: p99_uf.h:85
p99_uf
Definition: p99_uf.h:55
P99_DECLARE_STRUCT
#define P99_DECLARE_STRUCT(NAME)
forward declaration of a struct NAME
Definition: p99_type.h:59
p99_uf
struct p99_uf p99_uf
A simple Union-Find data structure.
Definition: p99_uf.h:53
p99_uf_union
int64_t p99_uf_union(p99_uf *uf, uint64_t left, uint64_t right)
Definition: p99_uf.h:163
p99_uf_destroy
void p99_uf_destroy(p99_uf const volatile *uf)
Definition: p99_uf.h:74
p99_uf_find
int64_t p99_uf_find(p99_uf const *uf, uint64_t pos)
Definition: p99_uf.h:115