Actual source code: ex62.c
1: static char help[] = "Tests `PetscGarbageKeySortedIntersect()`\n\n";
3: #include <petscsys.h>
4: #include <petsc/private/garbagecollector.h>
6: /* This program tests `PetscGarbageKeySortedIntersect(), which is the
7: public (MPI) interface to
8: `PetscErrorCode GarbageKeySortedIntersect_Private()`.
9: Sets are sent packed in arrays, with the first entry as the number of
10: set elements and the sets the remaining elements. This is because the
11: MPI reduction operation must have the call signature:
12: void PetscGarbageKeySortedIntersect(void *inset, void *inoutset, PetscMPIInt *length, MPI_Datatype *dtype)
13: This is a thin wrapper for the private routine:
14: PetscErrorCode GarbageKeySortedIntersect_Private(PetscInt64 seta[], PetscInt *lena, PetscInt64 setb[], PetscInt lenb)
15: Where
16: seta = (PetscInt64 *)inoutset;
17: setb = (PetscInt64 *)inset;
18: And the arguments are passed as:
19: &seta[1], (PetscInt *)&seta[0], &setb[1], (PetscInt)setb[0]
20: */
22: /* Populate a set with upto the first 49 unique Fibonnaci numbers */
23: PetscErrorCode Fibonnaci(PetscInt64 **set, PetscInt n)
24: {
25: PetscInt ii;
26: PetscInt64 fib[] = {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,
27: 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
28: 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025};
30: PetscFunctionBeginUser;
31: PetscAssert(n < 50, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "n must be less than 50");
32: PetscCall(PetscMalloc1(n + 1, set));
33: (*set)[0] = (PetscInt64)n;
34: for (ii = 0; ii < n; ii++) { (*set)[ii + 1] = fib[ii]; }
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: /* Populate a set with Square numbers */
39: PetscErrorCode Square(PetscInt64 **set, PetscInt n)
40: {
41: PetscInt64 ii;
43: PetscFunctionBeginUser;
44: PetscCall(PetscMalloc1(n + 1, set));
45: (*set)[0] = (PetscInt64)n;
46: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii; }
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: /* Populate a set with Cube numbers */
51: PetscErrorCode Cube(PetscInt64 **set, PetscInt n)
52: {
53: PetscInt64 ii;
55: PetscFunctionBeginUser;
56: PetscCall(PetscMalloc1(n + 1, set));
57: (*set)[0] = (PetscInt64)n;
58: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii; }
59: PetscFunctionReturn(PETSC_SUCCESS);
60: }
62: /* Populate a set with numbers to sixth power */
63: PetscErrorCode Sixth(PetscInt64 **set, PetscInt n)
64: {
65: PetscInt64 ii;
67: PetscFunctionBeginUser;
68: PetscCall(PetscMalloc1(n + 1, set));
69: (*set)[0] = (PetscInt64)n;
70: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii * ii * ii * ii; }
71: PetscFunctionReturn(PETSC_SUCCESS);
72: }
74: /* Print out the contents of a set */
75: PetscErrorCode PrintSet(PetscInt64 *set)
76: {
77: char text[64];
78: PetscInt ii;
80: PetscFunctionBeginUser;
81: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "["));
82: for (ii = 1; ii <= (PetscInt)set[0]; ii++) {
83: PetscCall(PetscFormatConvert(" %" PetscInt64_FMT ",", text));
84: PetscCall(PetscPrintf(PETSC_COMM_WORLD, text, set[ii]));
85: }
86: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
90: /* Check set equality */
91: PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
92: {
93: PetscInt ii;
95: PetscFunctionBeginUser;
96: PetscAssert(set[0] == true_set[0], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
97: for (ii = 1; ii < set[0] + 1; ii++) PetscAssert(set[ii] == true_set[ii], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets are different");
98: PetscFunctionReturn(PETSC_SUCCESS);
99: }
101: /* Tests functionality when two enpty sets are passed */
102: PetscErrorCode test_empty_empty()
103: {
104: PetscInt64 *set_a, *set_b;
105: PetscInt64 truth[] = {0};
106: PetscMPIInt length = 1;
108: PetscFunctionBeginUser;
109: PetscCall(PetscMalloc1(1, &set_a));
110: PetscCall(PetscMalloc1(1, &set_b));
112: set_a[0] = 0;
114: set_b[0] = 0;
116: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
117: PetscCall(PrintSet(set_a));
118: PetscCall(AssertSetsEqual(set_a, truth));
120: PetscCall(PetscFree(set_a));
121: PetscCall(PetscFree(set_b));
122: PetscFunctionReturn(PETSC_SUCCESS);
123: }
125: /* Tests functionality when seta is empty */
126: PetscErrorCode test_a_empty()
127: {
128: PetscInt64 *set_a, *set_b;
129: PetscInt64 truth[] = {0};
130: PetscMPIInt length = 1;
132: PetscFunctionBeginUser;
133: PetscCall(PetscMalloc1(1, &set_a));
134: PetscCall(PetscMalloc1(2, &set_b));
136: set_a[0] = 0;
138: set_b[0] = 1;
139: set_b[1] = 1;
141: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
142: PetscCall(PrintSet(set_a));
143: PetscCall(AssertSetsEqual(set_a, truth));
145: PetscCall(PetscFree(set_a));
146: PetscCall(PetscFree(set_b));
147: PetscFunctionReturn(PETSC_SUCCESS);
148: }
150: /* Tests functionality when setb is empty */
151: PetscErrorCode test_b_empty()
152: {
153: PetscInt64 *set_a, *set_b;
154: PetscInt64 truth[] = {0};
155: PetscMPIInt length = 1;
157: PetscFunctionBeginUser;
158: PetscCall(PetscMalloc1(2, &set_a));
159: PetscCall(PetscMalloc1(1, &set_b));
161: set_a[0] = 1;
162: set_a[1] = 1;
164: set_b[0] = 0;
166: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
167: PetscCall(PrintSet(set_a));
168: PetscCall(AssertSetsEqual(set_a, truth));
170: PetscCall(PetscFree(set_a));
171: PetscCall(PetscFree(set_b));
172: PetscFunctionReturn(PETSC_SUCCESS);
173: }
175: /* Tests functionality when both sets are identical */
176: PetscErrorCode test_identical()
177: {
178: PetscInt64 *set_a, *set_b;
179: PetscInt64 truth[] = {3, 1, 4, 9};
180: PetscMPIInt length = 4;
182: PetscFunctionBeginUser;
183: PetscCall(PetscMalloc1(4, &set_a));
184: PetscCall(PetscMalloc1(4, &set_b));
186: set_a[0] = 3;
187: set_a[1] = 1;
188: set_a[2] = 4;
189: set_a[3] = 9;
191: set_b[0] = 3;
192: set_b[1] = 1;
193: set_b[2] = 4;
194: set_b[3] = 9;
196: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
197: PetscCall(PrintSet(set_a));
198: PetscCall(AssertSetsEqual(set_a, truth));
200: PetscCall(PetscFree(set_a));
201: PetscCall(PetscFree(set_b));
202: PetscFunctionReturn(PETSC_SUCCESS);
203: }
205: /* Tests functionality when sets have no elements in common */
206: PetscErrorCode test_disjoint()
207: {
208: PetscInt64 *set_a, *set_b;
209: PetscInt64 truth[] = {0};
210: PetscMPIInt length = 1;
212: PetscFunctionBeginUser;
213: PetscCall(PetscMalloc1(4, &set_a));
214: PetscCall(PetscMalloc1(4, &set_b));
216: set_a[0] = 3;
217: set_a[1] = 1;
218: set_a[2] = 4;
219: set_a[3] = 9;
221: set_b[0] = 3;
222: set_b[1] = 2;
223: set_b[2] = 6;
224: set_b[3] = 8;
226: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
227: PetscCall(PrintSet(set_a));
228: PetscCall(AssertSetsEqual(set_a, truth));
230: PetscCall(PetscFree(set_a));
231: PetscCall(PetscFree(set_b));
232: PetscFunctionReturn(PETSC_SUCCESS);
233: }
235: /* Tests functionality when sets only have one element in common */
236: PetscErrorCode test_single_common()
237: {
238: PetscInt64 *set_a, *set_b;
239: PetscInt64 truth[] = {1, 4};
240: PetscMPIInt length = 1;
242: PetscFunctionBeginUser;
243: PetscCall(PetscMalloc1(4, &set_a));
244: PetscCall(PetscMalloc1(5, &set_b));
246: set_a[0] = 3;
247: set_a[1] = 1;
248: set_a[2] = 4;
249: set_a[3] = 9;
251: set_b[0] = 3;
252: set_b[1] = 2;
253: set_b[2] = 4;
254: set_b[3] = 6;
255: set_b[4] = 8;
257: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
258: PetscCall(PrintSet(set_a));
259: PetscCall(AssertSetsEqual(set_a, truth));
261: PetscCall(PetscFree(set_a));
262: PetscCall(PetscFree(set_b));
263: PetscFunctionReturn(PETSC_SUCCESS);
264: }
266: /* Specific test case flagged by PETSc issue #1247 */
267: PetscErrorCode test_issue_1247()
268: {
269: PetscInt64 *set_a, *set_b;
270: PetscInt64 truth[] = {0};
271: PetscMPIInt length = 1;
273: PetscFunctionBeginUser;
274: PetscCall(PetscMalloc1(3, &set_a));
275: PetscCall(PetscMalloc1(2, &set_b));
277: set_a[0] = 2;
278: set_a[1] = 2;
279: set_a[2] = 3;
281: set_b[0] = 1;
282: set_b[1] = 1;
284: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
285: PetscCall(PrintSet(set_a));
286: PetscCall(AssertSetsEqual(set_a, truth));
288: PetscCall(PetscFree(set_a));
289: PetscCall(PetscFree(set_b));
290: PetscFunctionReturn(PETSC_SUCCESS);
291: }
293: /* Tests functionality when seta is empty and setb is large */
294: PetscErrorCode test_empty_big()
295: {
296: PetscInt64 *set_a, *set_b;
297: PetscInt64 truth[] = {0};
298: PetscMPIInt length = 1;
300: PetscFunctionBeginUser;
301: PetscCall(PetscMalloc1(1, &set_a));
302: PetscCall(Square(&set_b, 999));
304: set_a[0] = 0;
306: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
307: PetscCall(PrintSet(set_a));
308: PetscCall(AssertSetsEqual(set_a, truth));
310: PetscCall(PetscFree(set_a));
311: PetscCall(PetscFree(set_b));
312: PetscFunctionReturn(PETSC_SUCCESS);
313: }
315: /* Tests functionality when seta is small and setb is large */
316: PetscErrorCode test_small_big()
317: {
318: PetscInt64 *set_a, *set_b;
319: PetscInt64 truth[] = {3, 1, 4, 9};
320: PetscMPIInt length = 1;
322: PetscFunctionBeginUser;
323: PetscCall(PetscMalloc1(5, &set_a));
324: PetscCall(Square(&set_b, 999));
326: set_a[0] = 4;
327: set_a[1] = 1;
328: set_a[2] = 4;
329: set_a[3] = 8;
330: set_a[4] = 9;
332: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
333: PetscCall(PrintSet(set_a));
334: PetscCall(AssertSetsEqual(set_a, truth));
336: PetscCall(PetscFree(set_a));
337: PetscCall(PetscFree(set_b));
338: PetscFunctionReturn(PETSC_SUCCESS);
339: }
341: /* Tests functionality when seta is medium sized and setb is large */
342: PetscErrorCode test_moderate_big()
343: {
344: PetscInt64 *set_a, *set_b;
345: PetscInt64 truth[] = {2, 1, 144};
346: PetscMPIInt length = 1;
348: PetscFunctionBeginUser;
349: PetscCall(Fibonnaci(&set_a, 49));
350: PetscCall(Square(&set_b, 999));
352: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
353: PetscCall(PrintSet(set_a));
354: PetscCall(AssertSetsEqual(set_a, truth));
356: PetscCall(PetscFree(set_a));
357: PetscCall(PetscFree(set_b));
358: PetscFunctionReturn(PETSC_SUCCESS);
359: }
361: /* Tests functionality when seta and setb are large */
362: PetscErrorCode test_big_big()
363: {
364: PetscInt64 *set_a, *set_b;
365: PetscInt64 *truth;
366: PetscMPIInt length = 1;
368: PetscFunctionBeginUser;
369: PetscCall(Cube(&set_a, 999));
370: PetscCall(Square(&set_b, 999));
372: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
373: PetscCall(PrintSet(set_a));
375: PetscCall(Sixth(&truth, 9));
376: PetscCall(AssertSetsEqual(set_a, truth));
378: PetscCall(PetscFree(set_a));
379: PetscCall(PetscFree(set_b));
380: PetscCall(PetscFree(truth));
381: PetscFunctionReturn(PETSC_SUCCESS);
382: }
384: /* Tests functionality when setb is empty and setb is large */
385: PetscErrorCode test_big_empty()
386: {
387: PetscInt64 *set_a, *set_b;
388: PetscInt64 truth[] = {0};
389: PetscMPIInt length = 1;
391: PetscFunctionBeginUser;
392: PetscCall(Cube(&set_a, 999));
393: PetscCall(PetscMalloc1(1, &set_b));
395: set_b[0] = 0;
397: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
398: PetscCall(PrintSet(set_a));
399: PetscCall(AssertSetsEqual(set_a, truth));
401: PetscCall(PetscFree(set_a));
402: PetscCall(PetscFree(set_b));
403: PetscFunctionReturn(PETSC_SUCCESS);
404: }
406: /* Tests functionality when setb is small and setb is large */
407: PetscErrorCode test_big_small()
408: {
409: PetscInt64 *set_a, *set_b;
410: PetscInt64 truth[] = {2, 1, 8};
411: PetscMPIInt length = 1;
413: PetscFunctionBeginUser;
414: PetscCall(Cube(&set_a, 999));
415: PetscCall(PetscMalloc1(5, &set_b));
417: set_b[0] = 4;
418: set_b[1] = 1;
419: set_b[2] = 4;
420: set_b[3] = 8;
421: set_b[4] = 9;
423: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
424: PetscCall(PrintSet(set_a));
425: PetscCall(AssertSetsEqual(set_a, truth));
427: PetscCall(PetscFree(set_a));
428: PetscCall(PetscFree(set_b));
429: PetscFunctionReturn(PETSC_SUCCESS);
430: }
432: /* Tests functionality when setb is medium sized and setb is large */
433: PetscErrorCode test_big_moderate()
434: {
435: PetscInt64 *set_a, *set_b;
436: PetscInt64 truth[] = {2, 1, 8};
437: PetscMPIInt length = 1;
439: PetscFunctionBeginUser;
440: PetscCall(Cube(&set_a, 999));
441: PetscCall(Fibonnaci(&set_b, 49));
443: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
444: PetscCall(PrintSet(set_a));
445: PetscCall(AssertSetsEqual(set_a, truth));
447: PetscCall(PetscFree(set_a));
448: PetscCall(PetscFree(set_b));
449: PetscFunctionReturn(PETSC_SUCCESS);
450: }
452: /* Tests functionality when seta and setb are large, in the opposite
453: order to test_big_big() */
454: PetscErrorCode test_big_big_reversed()
455: {
456: PetscInt64 *set_a, *set_b;
457: PetscInt64 *truth;
458: PetscMPIInt length = 1;
460: PetscFunctionBeginUser;
461: PetscCall(Cube(&set_a, 999));
462: PetscCall(Square(&set_b, 999));
464: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
465: PetscCall(PrintSet(set_a));
467: PetscCall(Sixth(&truth, 9));
468: PetscCall(AssertSetsEqual(set_a, truth));
470: PetscCall(PetscFree(set_a));
471: PetscCall(PetscFree(set_b));
472: PetscCall(PetscFree(truth));
473: PetscFunctionReturn(PETSC_SUCCESS);
474: }
476: /* Main executes the individual tests in a predefined order */
477: int main(int argc, char **argv)
478: {
479: PetscFunctionBeginUser;
480: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
482: /* Small tests */
483: /* Test different edge cases with small sets */
484: PetscCall(test_empty_empty());
485: PetscCall(test_a_empty());
486: PetscCall(test_b_empty());
487: PetscCall(test_identical());
488: PetscCall(test_disjoint());
489: PetscCall(test_single_common());
490: PetscCall(test_issue_1247());
492: /* Big tests */
493: /* Test different edge cases with big sets */
494: PetscCall(test_empty_big());
495: PetscCall(test_small_big());
496: PetscCall(test_moderate_big());
497: PetscCall(test_big_big());
498: PetscCall(test_big_empty());
499: PetscCall(test_big_small());
500: PetscCall(test_big_moderate());
501: PetscCall(test_big_big_reversed());
503: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
504: PetscCall(PetscFinalize());
505: return 0;
506: }
508: /*TEST
510: test:
511: suffix: 0
513: TEST*/