Loading...
Searching...
No Matches
tum_device.hpp
Go to the documentation of this file.
1#ifndef SEAMS_TUM_DEVICE_H_
2#define SEAMS_TUM_DEVICE_H_
3
17
18#ifdef SEAMS_HAS_OFFLOAD
19#pragma omp declare target
20#endif
21
22namespace tum {
23namespace device {
24
25inline bool bonded(const int *deg, const int *cols, int nAtoms, int kMax,
26 int a, int b) {
27 if (a < 0 || b < 0 || a >= nAtoms || b >= nAtoms) {
28 return false;
29 }
30 const int d = deg[a];
31 const int row = a * kMax;
32 for (int t = 0; t < d; ++t) {
33 if (cols[row + t] == b) {
34 return true;
35 }
36 }
37 return false;
38}
39
40inline bool inSix(const int *r, int atom) {
41 for (int t = 0; t < 6; ++t) {
42 if (r[t] == atom) {
43 return true;
44 }
45 }
46 return false;
47}
48
49inline bool shareAtoms(const int *a, const int *b) {
50 for (int i = 0; i < 6; ++i) {
51 if (inSix(b, a[i])) {
52 return true;
53 }
54 }
55 return false;
56}
57
58inline int commonCount(const int *a, const int *b) {
59 int n = 0;
60 for (int i = 0; i < 6; ++i) {
61 if (inSix(b, a[i])) {
62 ++n;
63 }
64 }
65 return n;
66}
67
68inline bool commonInThree(const int *a, const int *b, const int *c) {
69 for (int i = 0; i < 6; ++i) {
70 if (inSix(b, a[i]) && inSix(c, a[i])) {
71 return true;
72 }
73 }
74 return false;
75}
76
77inline bool shareNeigh(const int *deg, const int *cols, int nAtoms, int kMax,
78 int a, int b) {
79 const int da = deg[a];
80 const int ra = a * kMax;
81 for (int t = 0; t < da; ++t) {
82 if (bonded(deg, cols, nAtoms, kMax, b, cols[ra + t])) {
83 return true;
84 }
85 }
86 return false;
87}
88
91inline int hopsAtMost(const int *deg, const int *cols, int nAtoms, int kMax,
92 int a, int b, int cap) {
93 if (a == b) {
94 return 0;
95 }
96 if (bonded(deg, cols, nAtoms, kMax, a, b)) {
97 return 1;
98 }
99 if (cap < 2) {
100 return -1;
101 }
102 if (shareNeigh(deg, cols, nAtoms, kMax, a, b)) {
103 return 2;
104 }
105 return -1;
106}
107
109inline bool hopBoundPrimitiveSix(const int *r, const int *deg, const int *cols,
110 int nAtoms, int kMax) {
111 const int pairI[9] = {0, 1, 2, 3, 4, 5, 0, 1, 2};
112 const int pairJ[9] = {2, 3, 4, 5, 0, 1, 3, 4, 5};
113 const int ringHops[9] = {2, 2, 2, 2, 2, 2, 3, 3, 3};
114 for (int t = 0; t < 9; ++t) {
115 if (hopsAtMost(deg, cols, nAtoms, kMax, r[pairI[t]], r[pairJ[t]],
116 ringHops[t] - 1) >= 0) {
117 return false;
118 }
119 }
120 return true;
121}
122
123inline bool basalNeighbours(const int *deg, const int *cols, int nAtoms,
124 int kMax, int n1, int n2, int atomOne,
125 int atomTwo) {
126 const bool n1one = bonded(deg, cols, nAtoms, kMax, atomOne, n1);
127 const bool n1two = bonded(deg, cols, nAtoms, kMax, atomTwo, n1);
128 if (!n1one && !n1two) {
129 return false;
130 }
131 if (n1one) {
132 return bonded(deg, cols, nAtoms, kMax, atomTwo, n2);
133 }
134 return bonded(deg, cols, nAtoms, kMax, atomOne, n2);
135}
136
137inline bool notNeighboursOfRing(const int *deg, const int *cols, int nAtoms,
138 int kMax, const int *trip, const int *ring) {
139 for (int i = 0; i < 3; ++i) {
140 for (int j = 0; j < 6; ++j) {
141 if (bonded(deg, cols, nAtoms, kMax, ring[j], trip[i])) {
142 return false;
143 }
144 }
145 }
146 return true;
147}
148
149inline bool basalConditions(const int *deg, const int *cols, int nAtoms,
150 int kMax, const int *b1, const int *b2) {
151 int kIndex = -1;
152 int compare1 = 0;
153 int compare2 = 0;
154 bool l1n = false;
155 bool l2n = false;
156 const int l1 = b1[0];
157 const int l2 = b1[1];
158 for (int k = 0; k < 6; ++k) {
159 const int mk = b2[k];
160 if (bonded(deg, cols, nAtoms, kMax, l1, mk)) {
161 compare1 = b1[2];
162 compare2 = b1[4];
163 kIndex = k;
164 l1n = true;
165 break;
166 }
167 if (bonded(deg, cols, nAtoms, kMax, l2, mk)) {
168 compare1 = b1[3];
169 compare2 = b1[5];
170 kIndex = k;
171 l2n = true;
172 break;
173 }
174 }
175 if (!l1n && !l2n) {
176 return false;
177 }
178 int evenT[3];
179 int oddT[3];
180 int ie = 0;
181 int io = 0;
182 for (int k = 0; k <= 5; ++k) {
183 int ck = kIndex + k;
184 if (ck >= 6) {
185 ck -= 6;
186 }
187 if (k % 2 == 0) {
188 evenT[ie++] = b2[ck];
189 } else {
190 oddT[io++] = b2[ck];
191 }
192 }
193 if (!basalNeighbours(deg, cols, nAtoms, kMax, evenT[1], evenT[2], compare1,
194 compare2)) {
195 return false;
196 }
197 return notNeighboursOfRing(deg, cols, nAtoms, kMax, oddT, b1);
198}
199
200inline int firstRingThrough(const int *A, int nA, const int *B, int nB,
201 const int *C, int nC, int skipA, int skipB) {
202 int i = 0;
203 int j = 0;
204 int k = 0;
205 while (i < nA && j < nB && k < nC) {
206 const int x = A[i];
207 const int y = B[j];
208 const int z = C[k];
209 if (x == y && y == z) {
210 if (x != skipA && x != skipB) {
211 return x;
212 }
213 ++i;
214 ++j;
215 ++k;
216 continue;
217 }
218 int lo = x;
219 if (y < lo) {
220 lo = y;
221 }
222 if (z < lo) {
223 lo = z;
224 }
225 if (x == lo) {
226 ++i;
227 }
228 if (y == lo) {
229 ++j;
230 }
231 if (z == lo) {
232 ++k;
233 }
234 }
235 return -1;
236}
237
238inline int ringsThrough(const int *A, int nA, const int *B, int nB,
239 const int *C, int nC, int skipA, int skipB, int *out,
240 int cap) {
241 int i = 0;
242 int j = 0;
243 int k = 0;
244 int n = 0;
245 while (i < nA && j < nB && k < nC) {
246 const int x = A[i];
247 const int y = B[j];
248 const int z = C[k];
249 if (x == y && y == z) {
250 if (x != skipA && x != skipB && n < cap) {
251 out[n++] = x;
252 }
253 ++i;
254 ++j;
255 ++k;
256 continue;
257 }
258 int lo = x;
259 if (y < lo) {
260 lo = y;
261 }
262 if (z < lo) {
263 lo = z;
264 }
265 if (x == lo) {
266 ++i;
267 }
268 if (y == lo) {
269 ++j;
270 }
271 if (z == lo) {
272 ++k;
273 }
274 }
275 return n;
276}
277
278inline int fetchAdd(int *p) {
279 int old;
280#if defined(_OPENMP)
281#pragma omp atomic capture
282 old = (*p)++;
283#else
284 old = (*p)++;
285#endif
286 return old;
287}
288
290inline void enumSixFrom(int i, const int *deg, const int *cols, int nAtoms,
291 int kMax, int maxRings, int *nRings, int *ringAtoms,
292 int *dropped) {
293 const int di = deg[i];
294 if (di < 2) {
295 return;
296 }
297 const int irow = i * kMax;
298 for (int ia = 0; ia < di; ++ia) {
299 const int a = cols[irow + ia];
300 for (int ib = ia + 1; ib < di; ++ib) {
301 const int b = cols[irow + ib];
302 const int da = deg[a];
303 const int db = deg[b];
304 const int arow = a * kMax;
305 const int brow = b * kMax;
306 for (int ix = 0; ix < da; ++ix) {
307 const int x = cols[arow + ix];
308 if (x == i || x == b) {
309 continue;
310 }
311 for (int iy = 0; iy < db; ++iy) {
312 const int y = cols[brow + iy];
313 if (y == i || y == a || y == x) {
314 continue;
315 }
316 const int dx = deg[x];
317 const int xrow = x * kMax;
318 for (int iz = 0; iz < dx; ++iz) {
319 const int z = cols[xrow + iz];
320 if (z == i || z == a || z == b || z == y) {
321 continue;
322 }
323 if (!bonded(deg, cols, nAtoms, kMax, z, y)) {
324 continue;
325 }
326 const int cyc[6] = {i, a, x, z, y, b};
327 int mn = i;
328 for (int t = 1; t < 6; ++t) {
329 if (cyc[t] < mn) {
330 mn = cyc[t];
331 }
332 }
333 if (mn != i) {
334 continue;
335 }
336 if (!hopBoundPrimitiveSix(cyc, deg, cols, nAtoms, kMax)) {
337 continue;
338 }
339 const int slot = fetchAdd(nRings);
340 if (slot >= maxRings) {
341 fetchAdd(dropped);
342 continue;
343 }
344 const int dest = slot * 6;
345 for (int t = 0; t < 6; ++t) {
346 ringAtoms[dest + t] = cyc[t];
347 }
348 }
349 }
350 }
351 }
352 }
353}
354
355inline void invertOneRing(int r, const int *nRings, const int *ringAtoms,
356 int nAtoms, int maxPer, int *throughCount,
357 int *through) {
358 if (r >= *nRings) {
359 return;
360 }
361 const int *ring = ringAtoms + r * 6;
362 for (int t = 0; t < 6; ++t) {
363 const int atom = ring[t];
364 if (atom < 0 || atom >= nAtoms) {
365 continue;
366 }
367 const int slot = fetchAdd(throughCount + atom);
368 if (slot < maxPer) {
369 through[atom * maxPer + slot] = r;
370 }
371 }
372}
373
374inline void sortThroughRow(int *row, int n) {
375 for (int a = 1; a < n; ++a) {
376 const int key = row[a];
377 int p = a;
378 while (p > 0 && row[p - 1] > key) {
379 row[p] = row[p - 1];
380 --p;
381 }
382 row[p] = key;
383 }
384}
385
386inline void emitBasalFrom(int i, const int *nRings, const int *ringAtoms,
387 const int *deg, const int *cols,
388 const int *throughCount, const int *through,
389 int nAtoms, int kMax, int maxPer, int maxPairs,
390 int *nPairs, int *pairs) {
391 if (i >= *nRings) {
392 return;
393 }
394 const int *bi = ringAtoms + i * 6;
395 for (int slot = 0; slot < 2; ++slot) {
396 const int anchor = bi[slot];
397 if (anchor < 0 || anchor >= nAtoms) {
398 continue;
399 }
400 const int da = deg[anchor];
401 const int arow = anchor * kMax;
402 for (int n = 0; n < da; ++n) {
403 const int nb = cols[arow + n];
404 if (nb < 0 || nb >= nAtoms) {
405 continue;
406 }
407 const int nr = throughCount[nb];
408 const int *row = through + nb * maxPer;
409 for (int t = 0; t < nr; ++t) {
410 const int j = row[t];
411 if (j == i) {
412 continue;
413 }
414 const int *bj = ringAtoms + j * 6;
415 if (shareAtoms(bi, bj)) {
416 continue;
417 }
418 if (!basalConditions(deg, cols, nAtoms, kMax, bi, bj)) {
419 continue;
420 }
421 const int slotp = fetchAdd(nPairs);
422 if (slotp < maxPairs) {
423 pairs[slotp * 2] = i;
424 pairs[slotp * 2 + 1] = j;
425 }
426 }
427 }
428 }
429}
430
431inline void applyHcPair(int p, const int *nPairs, const int *pairs,
432 const int *ringAtoms, const int *throughCount,
433 const int *through, int nAtoms, int maxPer, int *hc) {
434 if (p >= *nPairs) {
435 return;
436 }
437 const int i = pairs[p * 2];
438 const int j = pairs[p * 2 + 1];
439 hc[i] = 1;
440 hc[j] = 1;
441 const int *bi = ringAtoms + i * 6;
442 const int *bj = ringAtoms + j * 6;
443 for (int q = 0; q < 6; ++q) {
444 int trip[3];
445 for (int m = 0; m < 3; ++m) {
446 trip[m] = bi[(q + m) % 6];
447 }
448 const int nA = throughCount[trip[0]];
449 const int nB = throughCount[trip[1]];
450 const int nC = throughCount[trip[2]];
451 const int *A = through + trip[0] * maxPer;
452 const int *B = through + trip[1] * maxPer;
453 const int *C = through + trip[2] * maxPer;
454 int cand[16];
455 const int nc = ringsThrough(A, nA, B, nB, C, nC, i, j, cand, 16);
456 for (int c = 0; c < nc; ++c) {
457 const int kr = cand[c];
458 const int *bk = ringAtoms + kr * 6;
459 int rest[3];
460 int nrst = 0;
461 for (int u = 0; u < 6; ++u) {
462 if (!inSix(trip, bk[u]) && nrst < 3) {
463 rest[nrst++] = bk[u];
464 }
465 }
466 if (nrst == 3 && commonCount(rest, bj) == 3) {
467 hc[kr] = 1;
468 }
469 }
470 }
471}
472
473inline void ddcFrom(int i, const int *nRings, const int *ringAtoms,
474 const int *throughCount, const int *through, const int *hc,
475 int nAtoms, int maxPer, int *ddc) {
476 if (i >= *nRings) {
477 return;
478 }
479 if (hc[i]) {
480 return;
481 }
482 const int *bi = ringAtoms + i * 6;
483 int peri[32];
484 int nPeri = 0;
485 for (int m = 0; m < 6; ++m) {
486 const int atom = bi[m];
487 if (atom < 0 || atom >= nAtoms) {
488 return;
489 }
490 const int nr = throughCount[atom];
491 const int *row = through + atom * maxPer;
492 int common = 0;
493 for (int t = 0; t < nr; ++t) {
494 if (row[t] == i) {
495 continue;
496 }
497 ++common;
498 if (nPeri < 32) {
499 peri[nPeri++] = row[t];
500 }
501 }
502 if (common < 3) {
503 return;
504 }
505 }
506 int newP[6];
507 for (int k = 0; k < 6; ++k) {
508 int trip[3];
509 for (int t = 0; t < 3; ++t) {
510 trip[t] = bi[(k + t) % 6];
511 }
512 const int nA = throughCount[trip[0]];
513 const int nB = throughCount[trip[1]];
514 const int nC = throughCount[trip[2]];
515 const int *A = through + trip[0] * maxPer;
516 const int *B = through + trip[1] * maxPer;
517 const int *C = through + trip[2] * maxPer;
518 const int j = firstRingThrough(A, nA, B, nB, C, nC, i, -1);
519 if (j < 0) {
520 return;
521 }
522 newP[k] = j;
523 }
524 const int *p0 = ringAtoms + newP[0] * 6;
525 const int *p1 = ringAtoms + newP[1] * 6;
526 const int *p2 = ringAtoms + newP[2] * 6;
527 const int *p3 = ringAtoms + newP[3] * 6;
528 const int *p4 = ringAtoms + newP[4] * 6;
529 const int *p5 = ringAtoms + newP[5] * 6;
530 if (!commonInThree(p0, p2, p4)) {
531 return;
532 }
533 if (!commonInThree(p1, p3, p5)) {
534 return;
535 }
536 const int *pairs[4][2] = {{p0, p2}, {p1, p3}, {p2, p4}, {p3, p5}};
537 for (int t = 0; t < 4; ++t) {
538 if (commonCount(pairs[t][0], pairs[t][1]) < 3) {
539 return;
540 }
541 }
542 ddc[i] = 1;
543 for (int t = 0; t < 6; ++t) {
544 ddc[newP[t]] = 1;
545 }
546}
547
548inline void atomIceFrom(int r, const int *nRings, const int *ringAtoms,
549 const int *hc, const int *ddc, int nAtoms, int *atomHc,
550 int *atomDdc) {
551 if (r >= *nRings) {
552 return;
553 }
554 const int *ring = ringAtoms + r * 6;
555 const int isHc = hc[r];
556 const int isDdc = ddc[r];
557 for (int t = 0; t < 6; ++t) {
558 const int a = ring[t];
559 if (a < 0 || a >= nAtoms) {
560 continue;
561 }
562 if (isHc) {
563 atomHc[a] = 1;
564 }
565 if (isDdc) {
566 atomDdc[a] = 1;
567 }
568 }
569}
570
571} // namespace device
572} // namespace tum
573
574#ifdef SEAMS_HAS_OFFLOAD
575#pragma omp end declare target
576#endif
577
578#endif
Topological network criteria functions.
bool shareNeigh(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b)
bool inSix(const int *r, int atom)
int fetchAdd(int *p)
int firstRingThrough(const int *A, int nA, const int *B, int nB, const int *C, int nC, int skipA, int skipB)
void enumSixFrom(int i, const int *deg, const int *cols, int nAtoms, int kMax, int maxRings, int *nRings, int *ringAtoms, int *dropped)
Enumerate hop-bound primitive six-rings whose lowest vertex is i.
void emitBasalFrom(int i, const int *nRings, const int *ringAtoms, const int *deg, const int *cols, const int *throughCount, const int *through, int nAtoms, int kMax, int maxPer, int maxPairs, int *nPairs, int *pairs)
void applyHcPair(int p, const int *nPairs, const int *pairs, const int *ringAtoms, const int *throughCount, const int *through, int nAtoms, int maxPer, int *hc)
void invertOneRing(int r, const int *nRings, const int *ringAtoms, int nAtoms, int maxPer, int *throughCount, int *through)
bool basalNeighbours(const int *deg, const int *cols, int nAtoms, int kMax, int n1, int n2, int atomOne, int atomTwo)
int ringsThrough(const int *A, int nA, const int *B, int nB, const int *C, int nC, int skipA, int skipB, int *out, int cap)
bool bonded(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b)
bool notNeighboursOfRing(const int *deg, const int *cols, int nAtoms, int kMax, const int *trip, const int *ring)
bool commonInThree(const int *a, const int *b, const int *c)
void sortThroughRow(int *row, int n)
void ddcFrom(int i, const int *nRings, const int *ringAtoms, const int *throughCount, const int *through, const int *hc, int nAtoms, int maxPer, int *ddc)
int commonCount(const int *a, const int *b)
void atomIceFrom(int r, const int *nRings, const int *ringAtoms, const int *hc, const int *ddc, int nAtoms, int *atomHc, int *atomDdc)
bool shareAtoms(const int *a, const int *b)
bool hopBoundPrimitiveSix(const int *r, const int *deg, const int *cols, int nAtoms, int kMax)
Hop-bounded Franzblau SP test on a six-cycle of the bond graph.
bool basalConditions(const int *deg, const int *cols, int nAtoms, int kMax, const int *b1, const int *b2)
int hopsAtMost(const int *deg, const int *cols, int nAtoms, int kMax, int a, int b, int cap)
Graph distance from a to b when it is at most cap, else -1.