Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

Loading...
Searching...
No Matches
FastUtils.h
Go to the documentation of this file.
1
32#pragma once
33
34#include <ogdf/basic/Graph.h>
36#include <ogdf/basic/System.h> // IWYU pragma: keep
37#include <ogdf/basic/basic.h>
38
39#include <cstddef>
40#include <cstdint>
41#include <iostream>
42#include <utility>
43#ifdef OGDF_SYSTEM_UNIX
44# include <sys/time.h>
45#endif
46
47#ifdef OGDF_FME_KERNEL_USE_SSE
49#endif
50
51namespace ogdf {
52namespace fast_multipole_embedder {
53
54// use SSE for Multipole computations
55//#define OGDF_FME_KERNEL_USE_SSE
56
57// simple parallel quadtree sort
58//#define OGDF_FME_PARALLEL_QUADTREE_SORT
59
60// use SSE for direct interaction (this is slower than the normal direct computation)
61//#define OGDF_FME_KERNEL_USE_SSE_DIRECT
62
63#ifndef OGDF_SSE3_EXTENSIONS
64// if we have no SSE3 these flags cannot be used (but they are sometime set nonethelless by CI for testing)
65# undef OGDF_FME_KERNEL_USE_SSE
66# undef OGDF_FME_KERNEL_USE_SSE_DIRECT
67#endif
68
69
70inline void OGDF_FME_Print_Config() {
71#ifdef OGDF_FME_KERNEL_USE_SSE
72 std::cout << "OGDF_FME_KERNEL_USE_SSE" << std::endl;
73#endif
74#ifdef OGDF_FME_PARALLEL_QUADTREE_SORT
75 std::cout << "OGDF_FME_PARALLEL_QUADTREE_SORT" << std::endl;
76#endif
77#ifdef OGDF_FME_KERNEL_USE_SSE_DIRECT
78 std::cout << "OGDF_FME_KERNEL_USE_SSE_DIRECT" << std::endl;
79#endif
80}
81
82using MortonNR = uint64_t;
83using CoordInt = uint32_t;
84
85template<typename T>
86inline bool is_align_16(T* ptr) {
87 return !(((size_t)(void*)ptr) & 0x0F);
88}
89
90template<typename T>
91inline T* align_16_prev_ptr(T* t) {
92 return (T*)(((size_t)((void*)t)) & ~0x0F);
93}
94
95template<typename T>
96inline T* align_16_next_ptr(T* t) {
97 return (T*)((((size_t)((void*)t)) + 15) & ~0x0F);
98}
99
100#ifdef OGDF_SYSTEM_UNIX
101inline timeval GetDiffTime(timeval _then, double& dtime) {
102 timeval then = (timeval)_then;
103 timeval now;
104 gettimeofday(&now, nullptr);
105 timeval diff;
106
107 diff.tv_sec = now.tv_sec - then.tv_sec;
108 diff.tv_usec = now.tv_usec - then.tv_usec;
109 while (diff.tv_usec < 0) {
110 diff.tv_sec--;
111 diff.tv_usec = 1000000 + now.tv_usec - then.tv_usec;
112 }
113
114 dtime = (double)diff.tv_sec;
115 dtime += (double)diff.tv_usec / 1e6;
116
117 return (timeval)now;
118}
119#endif
120
121inline void printProfiledTime(double t, const char* text) {
122 std::cout << t << "s\t" << text << std::endl;
123}
124
125inline void printProfiledTime(double t, double sum, const char* text) {
126 std::cout << t << "s\t" << text << "\t" << (t / sum) * 100.0 << "%" << std::endl;
127}
128
130#define OGDF_MALLOC_16(s) System::alignedMemoryAlloc16((s))
131
133#define OGDF_FREE_16(ptr) System::alignedMemoryFree((ptr))
134
136template<typename MNR_T, typename C_T>
137inline MNR_T mortonNumber(C_T ix, C_T iy) {
138 MNR_T x = (MNR_T)ix;
139 MNR_T y = (MNR_T)iy;
140 // bit length of the result
141 const unsigned int BIT_LENGTH = static_cast<unsigned int>(sizeof(MNR_T)) << 3;
142 // set all bits
143 MNR_T mask = 0x0;
144 mask = ~mask;
145
146 for (unsigned int i = (BIT_LENGTH >> 1); i > 0; i = i >> 1) {
147 // increase frequency
148 mask = mask ^ (mask << i);
149 x = (x | (x << i)) & mask;
150 y = (y | (y << i)) & mask;
151 }
152 return x | (y << 1);
153}
154
156template<typename MNR_T, typename C_T>
157inline void mortonNumberInv(MNR_T mnr, C_T& x, C_T& y) {
158 // bit length of the coordinates
159 unsigned int BIT_LENGTH = static_cast<unsigned int>(sizeof(C_T)) << 3;
160 // set least significant bit
161 MNR_T mask = 0x1;
162 // set coords to zero
163 x = y = 0;
164 for (unsigned int i = 0; i < BIT_LENGTH; i++) {
165 x = (C_T)(x | (mnr & mask));
166 mnr = mnr >> 1;
167 y = (C_T)(y | (mnr & mask));
168 mask = mask << 1;
169 }
170}
171
173template<typename T>
174inline uint32_t mostSignificantBit(T n) {
175 uint32_t BIT_LENGTH = static_cast<uint32_t>(sizeof(T)) << 3;
176 T mask = 0x1;
177 mask = mask << (BIT_LENGTH - 1);
178 for (uint32_t i = 0; i < BIT_LENGTH; i++) {
179 if (mask & n) {
180 return i;
181 }
182 mask = mask >> 1;
183 }
184 return BIT_LENGTH;
185}
186
188inline uint32_t prevPowerOfTwo(uint32_t n) {
189 uint32_t msb = 32 - mostSignificantBit(n);
190 return 0x1 << (msb - 1);
191}
192
195public:
197 explicit RandomNodeSet(const Graph& G) : m_graph(G) { allocate(); }
198
201
203 node chooseNode() const {
204 int i = m_numNodesChoosen
206 nodesLeft() - 1); //(int)((double)nodesLeft()*rand()/(RAND_MAX+1.0));
207 return m_array[i];
208 }
209
211 void removeNode(node v) {
212 int i = m_nodeIndex[v];
213 int j = m_numNodesChoosen;
214 node w = m_array[j];
215 std::swap(m_array[i], m_array[j]);
216 m_nodeIndex[w] = i;
217 m_nodeIndex[v] = j;
219 }
220
221 bool isAvailable(node v) const { return m_nodeIndex[v] >= m_numNodesChoosen; }
222
224 int nodesLeft() const { return m_numNodes - m_numNodesChoosen; }
225
226private:
227 void allocate() {
229 m_nodeIndex.init(m_graph);
232 int i = 0;
233 for (node v : m_graph.nodes) {
234 m_array[i] = v;
235 m_nodeIndex[v] = i;
236 i++;
237 }
238 }
239
240 void deallocate() { delete[] m_array; }
241
244
247
250
253
256};
257
258inline void gridGraph(Graph& G, int n, int m) {
259 G.clear();
260 node v;
261 node* topRow = new node[m];
262 topRow[0] = G.newNode();
263 for (int j = 1; j < m; j++) {
264 topRow[j] = G.newNode();
265 G.newEdge(topRow[j - 1], topRow[j]);
266 }
267 for (int i = 1; i < n; i++) {
268 v = G.newNode();
269 G.newEdge(topRow[0], v);
270 topRow[0] = v;
271 for (int j = 1; j < m; j++) {
272 v = G.newNode();
273 G.newEdge(topRow[j - 1], v);
274 G.newEdge(topRow[j], v);
275 topRow[j] = v;
276 }
277 }
278 delete[] topRow;
279}
280
281inline void randomGridGraph(Graph& G, int n, int m, double missinNodesPercentage = 0.03) {
282 gridGraph(G, n, m);
283 int numberOfNodesToDelete = (int)((double)G.numberOfNodes() * missinNodesPercentage);
284
285 RandomNodeSet rndSet(G);
286 for (int i = 0; i < numberOfNodesToDelete; i++) {
287 node v = rndSet.chooseNode();
288 rndSet.removeNode(v);
289 G.delNode(v);
290 }
291}
292
294template<class TYP>
295class BinCoeff {
296public:
297 explicit BinCoeff(unsigned int n) : m_max_n(n) { init_array(); }
298
300
302 void init_array() {
303 using ptr = TYP*;
304 unsigned int i, j;
305 m_binCoeffs = new ptr[m_max_n + 1];
306 for (i = 0; i <= m_max_n; i++) {
307 m_binCoeffs[i] = new TYP[i + 1];
308 }
309
310 //Pascalsches Dreieck
311 for (i = 0; i <= m_max_n; i++) {
312 m_binCoeffs[i][0] = m_binCoeffs[i][i] = 1;
313 }
314
315 for (i = 2; i <= m_max_n; i++) {
316 for (j = 1; j < i; j++) {
317 m_binCoeffs[i][j] = m_binCoeffs[i - 1][j - 1] + m_binCoeffs[i - 1][j];
318 }
319 }
320 }
321
323 void free_array() {
324 unsigned int i;
325 for (i = 0; i <= m_max_n; i++) {
326 delete[] m_binCoeffs[i];
327 }
328 delete[] m_binCoeffs;
329 }
330
331 //Returns n over k.
332 inline TYP value(unsigned int n, unsigned int k) const { return m_binCoeffs[n][k]; }
333
334private:
335 unsigned int m_max_n;
336
339};
340
341// nothing
342struct EmptyArgType { };
343
344//
345// Function Invoker for 8 args
346//
347template<typename FunctionType, typename ArgType1 = EmptyArgType, typename ArgType2 = EmptyArgType,
348 typename ArgType3 = EmptyArgType, typename ArgType4 = EmptyArgType,
349 typename ArgType5 = EmptyArgType, typename ArgType6 = EmptyArgType,
350 typename ArgType7 = EmptyArgType, typename ArgType8 = EmptyArgType>
352 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
353 ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7, ArgType8 _arg8)
354 : function(f)
355 , arg1(_arg1)
356 , arg2(_arg2)
357 , arg3(_arg3)
358 , arg4(_arg4)
359 , arg5(_arg5)
360 , arg6(_arg6)
361 , arg7(_arg7)
362 , arg8(_arg8) { }
363
364 inline void operator()() { function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
365
366 FunctionType function;
367 ArgType1 arg1;
368 ArgType2 arg2;
369 ArgType3 arg3;
370 ArgType4 arg4;
371 ArgType5 arg5;
372 ArgType6 arg6;
373 ArgType7 arg7;
374 ArgType8 arg8;
375};
376
377//
378// Function Invoker for 7 args
379//
380template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
381 typename ArgType4, typename ArgType5, typename ArgType6, typename ArgType7>
382struct FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6,
383 ArgType7, EmptyArgType> {
384 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
385 ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7)
386 : function(f)
387 , arg1(_arg1)
388 , arg2(_arg2)
389 , arg3(_arg3)
390 , arg4(_arg4)
391 , arg5(_arg5)
392 , arg6(_arg6)
393 , arg7(_arg7) { }
394
395 inline void operator()() { function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
396
397 FunctionType function;
398 ArgType1 arg1;
399 ArgType2 arg2;
400 ArgType3 arg3;
401 ArgType4 arg4;
402 ArgType5 arg5;
403 ArgType6 arg6;
404 ArgType7 arg7;
405};
406
407//
408// Function Invoker for 6 args
409//
410template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
411 typename ArgType4, typename ArgType5, typename ArgType6>
412struct FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6,
414 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
415 ArgType5 _arg5, ArgType6 _arg6)
416 : function(f), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5), arg6(_arg6) { }
417
418 inline void operator()() { function(arg1, arg2, arg3, arg4, arg5, arg6); }
419
420 FunctionType function;
421 ArgType1 arg1;
422 ArgType2 arg2;
423 ArgType3 arg3;
424 ArgType4 arg4;
425 ArgType5 arg5;
426 ArgType6 arg6;
427};
428
429//
430// Function Invoker for 5 args
431//
432template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
433 typename ArgType4, typename ArgType5>
434struct FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, EmptyArgType,
436 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
437 ArgType5 _arg5)
438 : function(f), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4), arg5(_arg5) { }
439
440 inline void operator()() { function(arg1, arg2, arg3, arg4, arg5); }
441
442 FunctionType function;
443 ArgType1 arg1;
444 ArgType2 arg2;
445 ArgType3 arg3;
446 ArgType4 arg4;
447 ArgType5 arg5;
448};
449
450//
451// Function Invoker for 4 args
452//
453template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3, typename ArgType4>
454struct FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, EmptyArgType, EmptyArgType,
456 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4)
457 : function(f), arg1(_arg1), arg2(_arg2), arg3(_arg3), arg4(_arg4) { }
458
459 inline void operator()() { function(arg1, arg2, arg3, arg4); }
460
461 FunctionType function;
462 ArgType1 arg1;
463 ArgType2 arg2;
464 ArgType3 arg3;
465 ArgType4 arg4;
466};
467
468//
469// Function Invoker for 3 args
470//
471template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3>
472struct FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, EmptyArgType, EmptyArgType,
474 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3)
475 : function(f), arg1(_arg1), arg2(_arg2), arg3(_arg3) { }
476
477 inline void operator()() { function(arg1, arg2, arg3); }
478
479 FunctionType function;
480 ArgType1 arg1;
481 ArgType2 arg2;
482 ArgType3 arg3;
483};
484
485//
486// Function Invoker for 2 args
487//
488template<typename FunctionType, typename ArgType1, typename ArgType2>
489struct FuncInvoker<FunctionType, ArgType1, ArgType2, EmptyArgType, EmptyArgType, EmptyArgType,
491 FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2)
492 : function(f), arg1(_arg1), arg2(_arg2) { }
493
494 inline void operator()() { function(arg1, arg2); }
495
496 FunctionType function;
497 ArgType1 arg1;
498 ArgType2 arg2;
499};
500
501//
502// Function Invoker for 1 args
503//
504template<typename FunctionType, typename ArgType1>
507 FuncInvoker(FunctionType f, ArgType1 _arg1) : function(f), arg1(_arg1) { }
508
509 inline void operator()() { function(arg1); }
510
511 FunctionType function;
512 ArgType1 arg1;
513};
514
515//
516// Function Invoker for 0 args
517//
518template<typename FunctionType>
521 FuncInvoker(FunctionType f) : function(f) { }
522
523 inline void operator()() { function(); }
524
525 FunctionType function;
526};
527
528template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
529 typename ArgType4, typename ArgType5, typename ArgType6, typename ArgType7, typename ArgType8>
531createFuncInvoker(FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
532 ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7, ArgType8 _arg8) {
533 return FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6,
534 ArgType7, ArgType8>(func, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8);
535}
536
537template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
538 typename ArgType4, typename ArgType5, typename ArgType6, typename ArgType7, typename ArgType8>
539FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8>
540createFuncInvoker(FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
541 ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7) {
542 return FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6,
543 ArgType7, EmptyArgType>(func, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7);
544}
545
546template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
547 typename ArgType4, typename ArgType5, typename ArgType6>
548FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6>
549createFuncInvoker(FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
550 ArgType5 _arg5, ArgType6 _arg6) {
552 func, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6);
553}
554
555template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3,
556 typename ArgType4, typename ArgType5>
558 FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4,
559 ArgType5 _arg5) {
561 _arg2, _arg3, _arg4, _arg5);
562}
563
564template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3, typename ArgType4>
566 FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4) {
568 _arg3, _arg4);
569}
570
571template<typename FunctionType, typename ArgType1, typename ArgType2, typename ArgType3>
573 ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3) {
574 return FuncInvoker<FunctionType, ArgType1, ArgType2, ArgType3>(func, _arg1, _arg2, _arg3);
575}
576
577template<typename FunctionType, typename ArgType1, typename ArgType2>
579 ArgType2 _arg2) {
580 return FuncInvoker<FunctionType, ArgType1, ArgType2>(func, _arg1, _arg2);
581}
582
583template<typename FunctionType, typename ArgType1>
584FuncInvoker<FunctionType, ArgType1> createFuncInvoker(FunctionType func, ArgType1 _arg1) {
585 return FuncInvoker<FunctionType, ArgType1>(func, _arg1);
586}
587
588template<typename FunctionType>
592
593}
594}
Includes declaration of graph class.
Decralation of GraphElement and GraphList classes.
Decalration of System class which provides unified access to system information.
Basic declarations, included by all source files.
Data type for general directed graphs (adjacency list representation).
Definition Graph_d.h:866
int numberOfNodes() const
Returns the number of nodes in the graph.
Definition Graph_d.h:979
internal::GraphObjectContainer< NodeElement > nodes
The container containing all node objects.
Definition Graph_d.h:929
Class for the representation of nodes.
Definition Graph_d.h:241
binomial coeffs from Hachuls FMMM
Definition FastUtils.h:295
void free_array()
Free space for BK.
Definition FastUtils.h:323
TYP ** m_binCoeffs
holds the binominal coefficients
Definition FastUtils.h:338
void init_array()
Init BK -matrix for values n, k in 0 to t.
Definition FastUtils.h:302
TYP value(unsigned int n, unsigned int k) const
Definition FastUtils.h:332
utility class to select multiple nodes randomly
Definition FastUtils.h:194
int nodesLeft() const
number of nodes available
Definition FastUtils.h:224
node chooseNode() const
chooses a node from the available nodes in O(1)
Definition FastUtils.h:203
NodeArray< int > m_nodeIndex
the index in the array of the nodes
Definition FastUtils.h:249
void removeNode(node v)
removes a node from available nodes (assumes v is available) in O(1)
Definition FastUtils.h:211
RandomNodeSet(const Graph &G)
init the random node set with the given graph. takes O(n)
Definition FastUtils.h:197
node * m_array
the set of all nodes (at the end the available nodes)
Definition FastUtils.h:246
RegisteredArray for nodes, edges and adjEntries of a graph.
Definition Graph_d.h:659
int randomNumber(int low, int high)
Returns random integer between low and high (including).
Include of header files for SSE-intrinsics.
void randomGridGraph(Graph &G, int n, int m, double missinNodesPercentage=0.03)
Definition FastUtils.h:281
uint32_t prevPowerOfTwo(uint32_t n)
returns the prev power of two
Definition FastUtils.h:188
void gridGraph(Graph &G, int n, int m)
Definition FastUtils.h:258
FuncInvoker< FunctionType, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8 > createFuncInvoker(FunctionType func, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4, ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7, ArgType8 _arg8)
Definition FastUtils.h:531
void printProfiledTime(double t, const char *text)
Definition FastUtils.h:121
MNR_T mortonNumber(C_T ix, C_T iy)
common template for bit-interleaving to compute the morton number assumes sizeOf(MNR_T) = 2*sizeOf(C_...
Definition FastUtils.h:137
void mortonNumberInv(MNR_T mnr, C_T &x, C_T &y)
common template for extracting the coordinates from a morton number assumes sizeOf(MNR_T) = 2*sizeOf(...
Definition FastUtils.h:157
uint32_t mostSignificantBit(T n)
returns the index of the most signficant bit set. 0 = most signif, bitlength-1 = least signif
Definition FastUtils.h:174
The namespace for all OGDF objects.
FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4, ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7)
Definition FastUtils.h:384
FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4, ArgType5 _arg5, ArgType6 _arg6)
Definition FastUtils.h:414
FuncInvoker(FunctionType f, ArgType1 _arg1, ArgType2 _arg2, ArgType3 _arg3, ArgType4 _arg4, ArgType5 _arg5, ArgType6 _arg6, ArgType7 _arg7, ArgType8 _arg8)
Definition FastUtils.h:352