6 * $Date: 2012-07-06 15:04:28 +0200 (Fr, 06. Jul 2012) $
7 ***************************************************************/
10 * \brief Definition of utility functions for FME layout.
12 * \author Martin Gronemann
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
43 #ifndef OGDF_FAST_UTILS_H
44 #define OGDF_FAST_UTILS_H
46 #include <ogdf/basic/GraphAttributes.h>
51 // use SSE for Multipole computations
52 //#define OGDF_FME_KERNEL_USE_SSE
54 // use special thread affinity (works only for unix and scatters the threads)
55 //#define OGDF_FME_THREAD_AFFINITY
57 // simple parallel quadtree sort
58 //#define OGDF_FME_PARALLEL_QUADTREE_SORT
60 // use SSE for direct interaction (this is slower than the normal direct computation)
61 //#define OGDF_FME_KERNEL_USE_SSE_DIRECT
63 inline void OGDF_FME_Print_Config()
65 #ifdef OGDF_FME_KERNEL_USE_SSE
66 std::cout
<< "OGDF_FME_KERNEL_USE_SSE" << std::endl
;
68 #ifdef OGDF_FME_THREAD_AFFINITY
69 std::cout
<< "OGDF_FME_THREAD_AFFINITY" << std::endl
;
71 #ifdef OGDF_FME_PARALLEL_QUADTREE_SORT
72 std::cout
<< "OGDF_FME_PARALLEL_QUADTREE_SORT" << std::endl
;
74 #ifdef OGDF_FME_KERNEL_USE_SSE_DIRECT
75 std::cout
<< "OGDF_FME_KERNEL_USE_SSE_DIRECT" << std::endl
;
79 #ifdef OGDF_FME_KERNEL_USE_SSE
80 #include <emmintrin.h>
81 #include <pmmintrin.h>
84 typedef __uint64 MortonNR
;
85 typedef __uint32 CoordInt
;
88 inline bool is_align_16(T
* ptr
)
90 return !(((size_t)(void*)ptr
) & 0x0F);
94 inline T
* align_16_prev_ptr(T
* t
)
96 return (T
*)(((size_t)((void*)t
))&~ 0x0F);
100 inline T
* align_16_next_ptr(T
* t
)
102 return (T
*)((((size_t)((void*)t
)) + 15)&~ 0x0F);
105 #ifdef OGDF_SYSTEM_UNIX
106 #include <sys/time.h>
107 inline timeval
GetDiffTime(timeval _then
, double& dtime
)
109 timeval then
= (timeval
) _then
;
111 gettimeofday(&now
, NULL
);
114 diff
.tv_sec
= now
.tv_sec
- then
.tv_sec
;
115 diff
.tv_usec
= now
.tv_usec
- then
.tv_usec
;
116 while(diff
.tv_usec
< 0)
119 diff
.tv_usec
= 1000000 + now
.tv_usec
- then
.tv_usec
;
123 dtime
+= (double) diff
.tv_usec
/ 1e6
;
125 return (timeval
) now
;
129 inline void printProfiledTime(double t
, const char* text
) { std::cout
<< t
<<"s\t" << text
<< std::endl
; };
130 inline void printProfiledTime(double t
, double sum
, const char* text
) { std::cout
<< t
<<"s\t" << text
<< "\t" << (t
/ sum
)*100.0 <<"%"<< std::endl
; };
131 //! Profile Macro to measure time with OGDF
132 #ifdef OGDF_SYSTEM_WINDOWS
133 #define FME_PROFILE(STATEMENT, TEXT) if(true) { double t=0.0;t=usedTime(t);STATEMENT;t=usedTime(t);std::cout << t <<"s\t" << TEXT << std::endl;};
135 #define FME_PROFILE(STATEMENT, TEXT) if(true) { double t=0.0;timeval start_time,end_time;gettimeofday(&start_time,0);STATEMENT;end_time=GetDiffTime(start_time,t);if (isMainThread()) std::cout << t <<"s\t" << TEXT << std::endl;};
138 //! 16-byte aligned memory allocation macro
139 #define MALLOC_16(s) System::alignedMemoryAlloc16((s))
141 //! 16-byte aligned memory deallocation macro
142 #define FREE_16(ptr) System::alignedMemoryFree((ptr))
144 //! square root of two
145 #define SQRT_OF_TWO 1.4142135623730950488016887242097
147 //! common template for bit-interleaving to compute the morton number assumes sizeOf(MNR_T) = 2*sizeOf(C_T)
148 template<typename MNR_T
, typename C_T
>
149 inline MNR_T
mortonNumber(C_T ix
, C_T iy
)
153 // bit length of the result
154 const unsigned int BIT_LENGTH
= sizeof(MNR_T
) << 3;
159 for (unsigned int i
= (BIT_LENGTH
>> 1);i
>0; i
= i
>> 1)
161 // increase frequency
162 mask
= mask
^ (mask
<< i
);
163 x
= (x
| (x
<< i
)) & mask
;
164 y
= (y
| (y
<< i
)) & mask
;
170 //! common template for extracting the coordinates from a morton number assumes sizeOf(MNR_T) = 2*sizeOf(C_T)
171 template<typename MNR_T
, typename C_T
>
172 inline void mortonNumberInv(MNR_T mnr
, C_T
& x
, C_T
& y
)
174 // bit length of the coordinates
175 unsigned int BIT_LENGTH
= sizeof(C_T
) << 3;
176 // set least significant bit
178 // set coords to zero
180 for (unsigned int i
=0; i
< BIT_LENGTH
; i
++)
182 x
= (C_T
)(x
| (mnr
& mask
));
184 y
= (C_T
)(y
| (mnr
& mask
));
189 //! returns the index of the most signficant bit set. 0 = most signif, bitlength-1 = least signif
191 inline __uint32
mostSignificantBit(T n
)
193 __uint32 BIT_LENGTH
= sizeof(T
) << 3;
195 mask
= mask
<< (BIT_LENGTH
- 1);
196 for (__uint32 i
= 0; i
< BIT_LENGTH
; i
++)
205 //! returns the prev power of two
206 inline __uint32
prevPowerOfTwo(__uint32 n
)
208 __uint32 msb
= 32 - mostSignificantBit(n
);
209 return 0x1 << (msb
- 1);
212 //! utility class to select multiple nodes randomly
216 //! init the random node set with the given graph. takes O(n)
217 RandomNodeSet(const Graph
& G
) : m_graph(G
) { allocate(); }
220 ~RandomNodeSet() { deallocate(); }
222 //! chooses a node from the available nodes in O(1)
223 node
chooseNode() const
225 int i
= m_numNodesChoosen
+ ogdf::randomNumber(0,nodesLeft()-1);//(int)((double)nodesLeft()*rand()/(RAND_MAX+1.0));
229 //! removes a node from available nodes (assumes v is available) in O(1)
230 void removeNode(node v
)
232 int i
= m_nodeIndex
[v
];
233 int j
= m_numNodesChoosen
;
235 swap(m_array
[i
], m_array
[j
]);
241 bool isAvailable(node v
) const { return (m_nodeIndex
[v
]>=m_numNodesChoosen
); }
243 //! number of nodes available;
244 int nodesLeft() const { return m_numNodes
- m_numNodesChoosen
; }
249 m_array
= new node
[m_graph
.numberOfNodes()];
250 m_nodeIndex
.init(m_graph
);
251 m_numNodes
= m_graph
.numberOfNodes();
252 m_numNodesChoosen
= 0;
255 forall_nodes(v
, m_graph
)
269 const Graph
& m_graph
;
271 //! the set of all nodes (at the end the available nodes)
274 //! the index in the array of the nodes
275 NodeArray
<int> m_nodeIndex
;
280 //! num available nodes
281 int m_numNodesChoosen
;
284 inline void gridGraph(Graph
& G
, int n
, int m
)
288 node
* topRow
= new node
[m
];
289 topRow
[0] = G
.newNode();;
290 for (int j
=1; j
<m
; j
++)
292 topRow
[j
] = G
.newNode();
293 G
.newEdge(topRow
[j
-1], topRow
[j
]);
295 for (int i
=1; i
<n
; i
++)
298 G
.newEdge(topRow
[0], v
);
300 for (int j
=1; j
<m
; j
++)
303 G
.newEdge(topRow
[j
-1], v
);
304 G
.newEdge(topRow
[j
], v
);
311 inline void randomGridGraph(Graph
& G
, int n
, int m
, double missinNodesPercentage
= 0.03)
314 int numberOfNodesToDelete
= (int)((double)G
.numberOfNodes() * missinNodesPercentage
);
316 RandomNodeSet
rndSet(G
);
317 for(int i
=0; i
<numberOfNodesToDelete
;i
++)
319 node v
= rndSet
.chooseNode();
320 rndSet
.removeNode(v
);
325 //! binomial coeffs from Hachuls FMMM
330 BinCoeff(unsigned int n
) : m_max_n(n
) { init_array(); }
332 ~BinCoeff() { free_array(); }
334 //! Init BK -matrix for values n, k in 0 to t.
339 m_binCoeffs
= new ptr
[m_max_n
+1];
340 for(i
= 0;i
<= m_max_n
;i
++)
342 m_binCoeffs
[i
]= new TYP
[i
+1];
345 //Pascalsches Dreieck
346 for (i
= 0; i
<= m_max_n
;i
++)
348 m_binCoeffs
[i
][0] = m_binCoeffs
[i
][i
] = 1;
351 for (i
= 2; i
<= m_max_n
; i
++)
353 for (j
= 1; j
< i
; j
++)
355 m_binCoeffs
[i
][j
] = m_binCoeffs
[i
-1][j
-1]+m_binCoeffs
[i
-1][j
];
360 //! Free space for BK.
364 for(i
= 0;i
<= m_max_n
;i
++)
366 delete[] m_binCoeffs
[i
];
368 delete[] m_binCoeffs
;
372 inline TYP
value(unsigned int n
, unsigned int k
) const
374 return m_binCoeffs
[n
][k
];
378 unsigned int m_max_n
;
380 //! holds the binominal coefficients
386 struct EmptyArgType
{};
388 // Function Invoker for 8 args
390 template<typename FunctionType
, typename ArgType1
= EmptyArgType
, typename ArgType2
= EmptyArgType
, typename ArgType3
= EmptyArgType
, typename ArgType4
= EmptyArgType
, typename ArgType5
= EmptyArgType
, typename ArgType6
= EmptyArgType
, typename ArgType7
= EmptyArgType
, typename ArgType8
= EmptyArgType
>
393 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
, ArgType7 _arg7
, ArgType8 _arg8
) :
394 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
), arg4(_arg4
), arg5(_arg5
), arg6(_arg6
), arg7(_arg7
), arg8(_arg8
) { }
396 inline void operator()() { function(arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
, arg8
); }
398 FunctionType function
;
411 // Function Invoker for 7 args
413 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
, typename ArgType6
, typename ArgType7
>
414 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, ArgType7
, EmptyArgType
>
416 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
, ArgType7 _arg7
) :
417 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
), arg4(_arg4
), arg5(_arg5
), arg6(_arg6
), arg7(_arg7
) { }
419 inline void operator()() { function(arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
); }
421 FunctionType function
;
432 // Function Invoker for 6 args
434 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
, typename ArgType6
>
435 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, EmptyArgType
, EmptyArgType
>
437 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
) :
438 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
), arg4(_arg4
), arg5(_arg5
), arg6(_arg6
) { }
440 inline void operator()() { function(arg1
, arg2
, arg3
, arg4
, arg5
, arg6
); }
442 FunctionType function
;
452 // Function Invoker for 5 args
454 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
>
455 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
457 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
) :
458 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
), arg4(_arg4
), arg5(_arg5
) { }
460 inline void operator()() { function(arg1
, arg2
, arg3
, arg4
, arg5
); }
462 FunctionType function
;
471 // Function Invoker for 4 args
473 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
>
474 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
476 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
) :
477 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
), arg4(_arg4
) { }
479 inline void operator()() { function(arg1
, arg2
, arg3
, arg4
); }
481 FunctionType function
;
489 // Function Invoker for 3 args
491 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
>
492 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
494 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
) :
495 function(f
), arg1(_arg1
), arg2(_arg2
), arg3(_arg3
) { }
497 inline void operator()() { function(arg1
, arg2
, arg3
); }
499 FunctionType function
;
506 // Function Invoker for 2 args
508 template<typename FunctionType
, typename ArgType1
, typename ArgType2
>
509 struct FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
511 FuncInvoker(FunctionType f
, ArgType1 _arg1
, ArgType2 _arg2
) :
512 function(f
), arg1(_arg1
), arg2(_arg2
) { }
514 inline void operator()() { function(arg1
, arg2
); }
516 FunctionType function
;
522 // Function Invoker for 1 args
524 template<typename FunctionType
, typename ArgType1
>
525 struct FuncInvoker
<FunctionType
, ArgType1
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
527 FuncInvoker(FunctionType f
, ArgType1 _arg1
) :
528 function(f
), arg1(_arg1
) { }
530 inline void operator()() { function(arg1
); }
532 FunctionType function
;
537 // Function Invoker for 0 args
539 template<typename FunctionType
>
540 struct FuncInvoker
<FunctionType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
, EmptyArgType
>
542 FuncInvoker(FunctionType f
) :
545 inline void operator()() { function(); }
547 FunctionType function
;
551 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
, typename ArgType6
, typename ArgType7
, typename ArgType8
>
552 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, ArgType7
, ArgType8
>
553 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
, ArgType7 _arg7
, ArgType8 _arg8
)
555 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, ArgType7
, ArgType8
>(func
, _arg1
, _arg2
, _arg3
, _arg4
, _arg5
, _arg6
, _arg7
, _arg8
);
558 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
, typename ArgType6
, typename ArgType7
, typename ArgType8
>
559 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, ArgType7
, ArgType8
>
560 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
, ArgType7 _arg7
)
562 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
, ArgType7
, EmptyArgType
>(func
, _arg1
, _arg2
, _arg3
, _arg4
, _arg5
, _arg6
, _arg7
);
565 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
, typename ArgType6
>
566 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
>
567 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
, ArgType6 _arg6
)
569 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
, ArgType6
>(func
, _arg1
, _arg2
, _arg3
, _arg4
, _arg5
, _arg6
);
572 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
, typename ArgType5
>
573 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
>
574 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
, ArgType5 _arg5
)
576 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
, ArgType5
>(func
, _arg1
, _arg2
, _arg3
, _arg4
, _arg5
);
579 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
, typename ArgType4
>
580 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
>
581 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
, ArgType4 _arg4
)
583 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
, ArgType4
>(func
, _arg1
, _arg2
, _arg3
, _arg4
);
586 template<typename FunctionType
, typename ArgType1
, typename ArgType2
, typename ArgType3
>
587 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
>
588 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
, ArgType3 _arg3
)
590 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
, ArgType3
>(func
, _arg1
, _arg2
, _arg3
);
593 template<typename FunctionType
, typename ArgType1
, typename ArgType2
>
594 FuncInvoker
<FunctionType
, ArgType1
, ArgType2
>
595 createFuncInvoker(FunctionType func
, ArgType1 _arg1
, ArgType2 _arg2
)
597 return FuncInvoker
<FunctionType
, ArgType1
, ArgType2
>(func
, _arg1
, _arg2
);
600 template<typename FunctionType
, typename ArgType1
>
601 FuncInvoker
<FunctionType
, ArgType1
>
602 createFuncInvoker(FunctionType func
, ArgType1 _arg1
)
604 return FuncInvoker
<FunctionType
, ArgType1
>(func
, _arg1
);
607 template<typename FunctionType
>
608 FuncInvoker
<FunctionType
>
609 createFuncInvoker(FunctionType func
)
611 return FuncInvoker
<FunctionType
>(func
);
616 #endif // fast utils h