Open
Graph Drawing
Framework

 v. 2023.09 (Elderberry)
 

utils.h
Go to the documentation of this file.
1 
29 #pragma once
30 
31 #include <cstddef>
32 #include <type_traits>
33 
34 namespace ogdf {
35 namespace energybased {
36 namespace dtree {
37 
38 template<typename IntType, int Dim>
40  const IntType a[Dim], const IntType b[Dim]) {
41  // loop over the dimension
42  for (int d = Dim - 1; d >= 0; d--) {
43  // if the block is different
44  if (a[d] != b[d]) {
45  return false;
46  }
47  }
48  return true;
49 }
50 
51 // special tuned version for unsigned int and dim = 1
52 template<typename IntType, int Dim>
53 inline typename std::enable_if<Dim == 1, bool>::type mortonComparerEqual(const IntType a[Dim],
54  const IntType b[Dim]) {
55  return a[0] == b[0];
56 }
57 
58 // special tuned version for unsigned int and dim = 2
59 template<typename IntType, int Dim>
60 inline typename std::enable_if<Dim == 2, bool>::type mortonComparerEqual(const IntType a[Dim],
61  const IntType b[Dim]) {
62  return a[0] == b[0] && a[1] == b[1];
63 }
64 
65 template<typename IntType, int Dim>
67  const IntType a[Dim], const IntType b[Dim]) {
68  // loop over the dimension
69  for (int d = Dim - 1; d >= 0; d--) {
70  // if the block is different
71  if (a[d] != b[d]) {
72  return a[d] < b[d];
73  }
74  }
75  return false;
76 }
77 
78 // special tuned version for unsigned int and dim = 1
79 template<typename IntType, int Dim>
80 inline typename std::enable_if<Dim == 1, bool>::type mortonComparerLess(const unsigned int a[Dim],
81  const unsigned int b[Dim]) {
82  return a[0] < b[0];
83 }
84 
85 // special tuned version for unsigned int and dim = 2
86 template<typename IntType, int Dim>
87 inline typename std::enable_if<Dim == 2, bool>::type mortonComparerLess(const unsigned int a[Dim],
88  const unsigned int b[Dim]) {
89  return (a[1] == b[1]) ? a[0] < b[0] : a[1] < b[1];
90 }
91 
92 template<typename IntType, int Dim>
94  const IntType coords[Dim], IntType mnr[Dim]) {
95  // number of bits of the grid coord type
96  const int BitLength = sizeof(IntType) << 3;
97 
98  // loop over the dimension
99  for (int d = 0; d < Dim; d++) {
100  // reset the mnr
101  mnr[d] = 0x0;
102  }
103 
104  // counter for the res bit
105  int k = 0;
106 
107  // now loop over all bits
108  for (int i = 0; i < BitLength; ++i) {
109  // loop over the dimension
110  for (int d = 0; d < Dim; d++) {
111  // set the k-th bit in the correct block at the k % position
112  mnr[k / BitLength] |= ((coords[d] >> i) & 0x1) << (k % BitLength);
113 
114  // stupid increment
115  k++;
116  }
117  };
118 }
119 
120 template<typename IntType, int Dim>
121 inline typename std::enable_if<Dim == 1, void>::type interleaveBits(const unsigned int coords[Dim],
122  unsigned int mnr[Dim]) {
123  mnr[0] = coords[0];
124 }
125 
126 template<typename IntType, int Dim>
127 inline typename std::enable_if<Dim == 2, void>::type interleaveBits(const unsigned int coords[Dim],
128  unsigned int mnr[Dim]) {
129  // half the bit length = #bytes * 4
130  const size_t HalfBitLength = sizeof(unsigned int) << 2;
131 
132  // reset the mnr
133  mnr[0] = 0x0;
134  mnr[1] = 0x0;
135 
136  // this variable is used to generate an alternating pattern for the
137  // lower half bits of both coords (the higher half will be shifted out later)
138  unsigned int x_lo[2] = {coords[0], coords[1]};
139 
140  // this one is used for the higher half, thus, we shift them to right
141  unsigned int x_hi[2] = {coords[0] >> HalfBitLength, coords[1] >> HalfBitLength};
142 
143  // a mask full of 1's
144  unsigned int mask = ~0x0;
145 
146  for (unsigned int i = (HalfBitLength); i > 0; i = i >> 1) {
147  // increase frequency
148  // generates step by step: ..., 11110000, 11001100, 10101010
149  mask = mask ^ (mask << i);
150 
151  // create an alternating 0x0x0x0x0x pattern for the lower bits
152  x_lo[0] = (x_lo[0] | (x_lo[0] << i)) & mask;
153  x_lo[1] = (x_lo[1] | (x_lo[1] << i)) & mask;
154  // and for the higher bits too
155  x_hi[0] = (x_hi[0] | (x_hi[0] << i)) & mask;
156  x_hi[1] = (x_hi[1] | (x_hi[1] << i)) & mask;
157  };
158 
159  // save the lower bits alternating in the first block
160  mnr[0] = x_lo[0] | (x_lo[1] << 1);
161 
162  // the higher go into the second block
163  mnr[1] = x_hi[0] | (x_hi[1] << 1);
164 }
165 
166 template<typename IntType>
167 inline int mostSignificantBit(IntType x) {
168  // number of bits of the int type
169  const size_t BitLength = sizeof(IntType) << 3;
170 
171  // the index 0... BitLength - 1 of the msb
172  int result = 0;
173 
174  // binary search on the bits of x
175  for (unsigned int i = (BitLength >> 1); i > 0; i = i >> 1) {
176  // check if anything left of i - 1 is set
177  if (x >> i) {
178  // it is msb must be in that half
179  x = x >> i;
180 
181  // msb > i
182  result += i;
183  }
184  }
185 
186  // return the result
187  return result;
188 }
189 
190 template<typename IntType, int Dim>
192  const IntType b[Dim]) {
193  // number of bits of the grid coord type
194  const size_t BitLength = sizeof(IntType) << 3;
195 
196  // loop over the dimension
197  for (int d = Dim - 1; d >= 0; d--) {
198  // if the block is different
199  if (a[d] != b[d]) {
200  int msb = (mostSignificantBit<IntType>(a[d] ^ b[d]) + (d * BitLength));
201 
202  // the lowest common ancestor level is msb / num coords
203  return msb / Dim;
204  }
205  }
206 
207  return 0;
208 }
209 
210 template<typename IntType, int Dim>
212  const unsigned int a[Dim], const unsigned int b[Dim]) {
213  return mostSignificantBit<unsigned int>(a[0] ^ b[0]);
214 }
215 
216 }
217 }
218 }
ogdf
The namespace for all OGDF objects.
Definition: multilevelmixer.cpp:39
ogdf::energybased::dtree::interleaveBits
std::enable_if< Dim !=1 &&Dim !=2, void >::type interleaveBits(const IntType coords[Dim], IntType mnr[Dim])
Definition: utils.h:93
ogdf::energybased::dtree::lowestCommonAncestorLevel
std::enable_if< Dim !=1, int >::type lowestCommonAncestorLevel(const IntType a[Dim], const IntType b[Dim])
Definition: utils.h:191
backward::Color::type
type
Definition: backward.hpp:1716
ogdf::energybased::dtree::mortonComparerLess
std::enable_if< Dim !=1 &&Dim !=2, bool >::type mortonComparerLess(const IntType a[Dim], const IntType b[Dim])
Definition: utils.h:66
ogdf::energybased::dtree::mostSignificantBit
int mostSignificantBit(IntType x)
Definition: utils.h:167
ogdf::energybased::dtree::mortonComparerEqual
std::enable_if< Dim !=1 &&Dim !=2, bool >::type mortonComparerEqual(const IntType a[Dim], const IntType b[Dim])
Definition: utils.h:39