Actual source code: ex62.c
2: static char help[] = "Tests `PetscGarbageKeySortedIntersect()`\n\n";
4: #include <petscsys.h>
5: #include <petsc/private/garbagecollector.h>
7: /* This program tests `PetscGarbageKeySortedIntersect(), which is the
8: public (MPI) interface to
9: `PetscErrorCode GarbageKeySortedIntersect_Private()`.
10: Sets are sent packed in arrays, with the first entry as the number of
11: set elements and the sets the remaining elements. This is because the
12: MPI reduction operation must have the call signature:
13: void PetscGarbageKeySortedIntersect(void *inset, void *inoutset, PetscMPIInt *length, MPI_Datatype *dtype)
14: This is a thin wrapper for the private routine:
15: PetscErrorCode GarbageKeySortedIntersect_Private(PetscInt64 seta[], PetscInt *lena, PetscInt64 setb[], PetscInt lenb)
16: Where
17: seta = (PetscInt64 *)inoutset;
18: setb = (PetscInt64 *)inset;
19: And the arguments are passed as:
20: &seta[1], (PetscInt *)&seta[0], &setb[1], (PetscInt)setb[0]
21: */
23: /* Populate a set with upto the first 49 unique Fibonnaci numbers */
24: PetscErrorCode Fibonnaci(PetscInt64 **set, PetscInt n)
25: {
26: PetscInt ii;
27: PetscInt64 fib[] = {1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584,
28: 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
29: 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025};
31: PetscFunctionBeginUser;
32: PetscAssert((n < 50), PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "n must be less than 50\n");
33: PetscCall(PetscMalloc1(n + 1, set));
34: (*set)[0] = (PetscInt64)n;
35: for (ii = 0; ii < n; ii++) { (*set)[ii + 1] = fib[ii]; }
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: /* Populate a set with Square numbers */
40: PetscErrorCode Square(PetscInt64 **set, PetscInt n)
41: {
42: PetscInt64 ii;
44: PetscFunctionBeginUser;
45: PetscCall(PetscMalloc1(n + 1, set));
46: (*set)[0] = (PetscInt64)n;
47: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii; }
48: PetscFunctionReturn(PETSC_SUCCESS);
49: }
51: /* Populate a set with Cube numbers */
52: PetscErrorCode Cube(PetscInt64 **set, PetscInt n)
53: {
54: PetscInt64 ii;
56: PetscFunctionBeginUser;
57: PetscCall(PetscMalloc1(n + 1, set));
58: (*set)[0] = (PetscInt64)n;
59: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii; }
60: PetscFunctionReturn(PETSC_SUCCESS);
61: }
63: /* Populate a set with numbers to sixth power */
64: PetscErrorCode Sixth(PetscInt64 **set, PetscInt n)
65: {
66: PetscInt64 ii;
68: PetscFunctionBeginUser;
69: PetscCall(PetscMalloc1(n + 1, set));
70: (*set)[0] = (PetscInt64)n;
71: for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii * ii * ii * ii; }
72: PetscFunctionReturn(PETSC_SUCCESS);
73: }
75: /* Print out the contents of a set */
76: PetscErrorCode PrintSet(PetscInt64 *set)
77: {
78: char text[64];
79: PetscInt ii;
81: PetscFunctionBeginUser;
82: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "["));
83: for (ii = 1; ii <= (PetscInt)set[0]; ii++) {
84: PetscCall(PetscFormatConvert(" %" PetscInt64_FMT ",", text));
85: PetscCall(PetscPrintf(PETSC_COMM_WORLD, text, set[ii]));
86: }
87: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
88: PetscFunctionReturn(PETSC_SUCCESS);
89: }
91: /* Check set equality */
92: PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
93: {
94: PetscInt ii;
96: PetscFunctionBeginUser;
97: PetscAssert((set[0] == true_set[0]), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
98: for (ii = 1; ii < set[0] + 1; ii++) PetscAssert((set[ii] == true_set[ii]), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets are different");
99: PetscFunctionReturn(PETSC_SUCCESS);
100: }
102: /* Tests functionality when two enpty sets are passed */
103: PetscErrorCode test_empty_empty()
104: {
105: PetscInt64 *set_a, *set_b;
106: PetscInt64 truth[] = {0};
107: PetscMPIInt length = 1;
109: PetscFunctionBeginUser;
111: PetscCall(PetscMalloc1(1, &set_a));
112: PetscCall(PetscMalloc1(1, &set_b));
114: set_a[0] = 0;
116: set_b[0] = 0;
118: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
119: PetscCall(PrintSet(set_a));
120: PetscCall(AssertSetsEqual(set_a, truth));
122: PetscCall(PetscFree(set_a));
123: PetscCall(PetscFree(set_b));
125: PetscFunctionReturn(PETSC_SUCCESS);
126: }
128: /* Tests functionality when seta is empty */
129: PetscErrorCode test_a_empty()
130: {
131: PetscInt64 *set_a, *set_b;
132: PetscInt64 truth[] = {0};
133: PetscMPIInt length = 1;
135: PetscFunctionBeginUser;
137: PetscCall(PetscMalloc1(1, &set_a));
138: PetscCall(PetscMalloc1(2, &set_b));
140: set_a[0] = 0;
142: set_b[0] = 1;
143: set_b[1] = 1;
145: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
146: PetscCall(PrintSet(set_a));
147: PetscCall(AssertSetsEqual(set_a, truth));
149: PetscCall(PetscFree(set_a));
150: PetscCall(PetscFree(set_b));
152: PetscFunctionReturn(PETSC_SUCCESS);
153: }
155: /* Tests functionality when setb is empty */
156: PetscErrorCode test_b_empty()
157: {
158: PetscInt64 *set_a, *set_b;
159: PetscInt64 truth[] = {0};
160: PetscMPIInt length = 1;
162: PetscFunctionBeginUser;
164: PetscCall(PetscMalloc1(2, &set_a));
165: PetscCall(PetscMalloc1(1, &set_b));
167: set_a[0] = 1;
168: set_a[1] = 1;
170: set_b[0] = 0;
172: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
173: PetscCall(PrintSet(set_a));
174: PetscCall(AssertSetsEqual(set_a, truth));
176: PetscCall(PetscFree(set_a));
177: PetscCall(PetscFree(set_b));
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
182: /* Tests functionality when both sets are identical */
183: PetscErrorCode test_identical()
184: {
185: PetscInt64 *set_a, *set_b;
186: PetscInt64 truth[] = {3, 1, 4, 9};
187: PetscMPIInt length = 4;
189: PetscFunctionBeginUser;
191: PetscCall(PetscMalloc1(4, &set_a));
192: PetscCall(PetscMalloc1(4, &set_b));
194: set_a[0] = 3;
195: set_a[1] = 1;
196: set_a[2] = 4;
197: set_a[3] = 9;
199: set_b[0] = 3;
200: set_b[1] = 1;
201: set_b[2] = 4;
202: set_b[3] = 9;
204: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
205: PetscCall(PrintSet(set_a));
206: PetscCall(AssertSetsEqual(set_a, truth));
208: PetscCall(PetscFree(set_a));
209: PetscCall(PetscFree(set_b));
211: PetscFunctionReturn(PETSC_SUCCESS);
212: }
214: /* Tests functionality when sets have no elements in common */
215: PetscErrorCode test_disjoint()
216: {
217: PetscInt64 *set_a, *set_b;
218: PetscInt64 truth[] = {0};
219: PetscMPIInt length = 1;
221: PetscFunctionBeginUser;
223: PetscCall(PetscMalloc1(4, &set_a));
224: PetscCall(PetscMalloc1(4, &set_b));
226: set_a[0] = 3;
227: set_a[1] = 1;
228: set_a[2] = 4;
229: set_a[3] = 9;
231: set_b[0] = 3;
232: set_b[1] = 2;
233: set_b[2] = 6;
234: set_b[3] = 8;
236: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
237: PetscCall(PrintSet(set_a));
238: PetscCall(AssertSetsEqual(set_a, truth));
240: PetscCall(PetscFree(set_a));
241: PetscCall(PetscFree(set_b));
243: PetscFunctionReturn(PETSC_SUCCESS);
244: }
246: /* Tests functionality when sets only have one element in common */
247: PetscErrorCode test_single_common()
248: {
249: PetscInt64 *set_a, *set_b;
250: PetscInt64 truth[] = {1, 4};
251: PetscMPIInt length = 1;
253: PetscFunctionBeginUser;
255: PetscCall(PetscMalloc1(4, &set_a));
256: PetscCall(PetscMalloc1(5, &set_b));
258: set_a[0] = 3;
259: set_a[1] = 1;
260: set_a[2] = 4;
261: set_a[3] = 9;
263: set_b[0] = 3;
264: set_b[1] = 2;
265: set_b[2] = 4;
266: set_b[3] = 6;
267: set_b[4] = 8;
269: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
270: PetscCall(PrintSet(set_a));
271: PetscCall(AssertSetsEqual(set_a, truth));
273: PetscCall(PetscFree(set_a));
274: PetscCall(PetscFree(set_b));
276: PetscFunctionReturn(PETSC_SUCCESS);
277: }
279: /* Specific test case flagged by PETSc issue #1247 */
280: PetscErrorCode test_issue_1247()
281: {
282: PetscInt64 *set_a, *set_b;
283: PetscInt64 truth[] = {0};
284: PetscMPIInt length = 1;
286: PetscFunctionBeginUser;
288: PetscCall(PetscMalloc1(3, &set_a));
289: PetscCall(PetscMalloc1(2, &set_b));
291: set_a[0] = 2;
292: set_a[1] = 2;
293: set_a[2] = 3;
295: set_b[0] = 1;
296: set_b[1] = 1;
298: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
299: PetscCall(PrintSet(set_a));
300: PetscCall(AssertSetsEqual(set_a, truth));
302: PetscCall(PetscFree(set_a));
303: PetscCall(PetscFree(set_b));
305: PetscFunctionReturn(PETSC_SUCCESS);
306: }
308: /* Tests functionality when seta is empty and setb is large */
309: PetscErrorCode test_empty_big()
310: {
311: PetscInt64 *set_a, *set_b;
312: PetscInt64 truth[] = {0};
313: PetscMPIInt length = 1;
315: PetscFunctionBeginUser;
317: PetscCall(PetscMalloc1(1, &set_a));
318: PetscCall(Square(&set_b, 999));
320: set_a[0] = 0;
322: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
323: PetscCall(PrintSet(set_a));
324: PetscCall(AssertSetsEqual(set_a, truth));
326: PetscCall(PetscFree(set_a));
327: PetscCall(PetscFree(set_b));
329: PetscFunctionReturn(PETSC_SUCCESS);
330: }
332: /* Tests functionality when seta is small and setb is large */
333: PetscErrorCode test_small_big()
334: {
335: PetscInt64 *set_a, *set_b;
336: PetscInt64 truth[] = {3, 1, 4, 9};
337: PetscMPIInt length = 1;
339: PetscFunctionBeginUser;
341: PetscCall(PetscMalloc1(5, &set_a));
342: PetscCall(Square(&set_b, 999));
344: set_a[0] = 4;
345: set_a[1] = 1;
346: set_a[2] = 4;
347: set_a[3] = 8;
348: set_a[4] = 9;
350: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
351: PetscCall(PrintSet(set_a));
352: PetscCall(AssertSetsEqual(set_a, truth));
354: PetscCall(PetscFree(set_a));
355: PetscCall(PetscFree(set_b));
357: PetscFunctionReturn(PETSC_SUCCESS);
358: }
360: /* Tests functionality when seta is medium sized and setb is large */
361: PetscErrorCode test_moderate_big()
362: {
363: PetscInt64 *set_a, *set_b;
364: PetscInt64 truth[] = {2, 1, 144};
365: PetscMPIInt length = 1;
367: PetscFunctionBeginUser;
369: PetscCall(Fibonnaci(&set_a, 49));
370: PetscCall(Square(&set_b, 999));
372: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
373: PetscCall(PrintSet(set_a));
374: PetscCall(AssertSetsEqual(set_a, truth));
376: PetscCall(PetscFree(set_a));
377: PetscCall(PetscFree(set_b));
379: PetscFunctionReturn(PETSC_SUCCESS);
380: }
382: /* Tests functionality when seta and setb are large */
383: PetscErrorCode test_big_big()
384: {
385: PetscInt64 *set_a, *set_b;
386: PetscInt64 *truth;
387: PetscMPIInt length = 1;
389: PetscFunctionBeginUser;
391: PetscCall(Cube(&set_a, 999));
392: PetscCall(Square(&set_b, 999));
394: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
395: PetscCall(PrintSet(set_a));
397: PetscCall(Sixth(&truth, 9));
398: PetscCall(AssertSetsEqual(set_a, truth));
400: PetscCall(PetscFree(set_a));
401: PetscCall(PetscFree(set_b));
402: PetscCall(PetscFree(truth));
404: PetscFunctionReturn(PETSC_SUCCESS);
405: }
407: /* Tests functionality when setb is empty and setb is large */
408: PetscErrorCode test_big_empty()
409: {
410: PetscInt64 *set_a, *set_b;
411: PetscInt64 truth[] = {0};
412: PetscMPIInt length = 1;
414: PetscFunctionBeginUser;
416: PetscCall(Cube(&set_a, 999));
417: PetscCall(PetscMalloc1(1, &set_b));
419: set_b[0] = 0;
421: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
422: PetscCall(PrintSet(set_a));
423: PetscCall(AssertSetsEqual(set_a, truth));
425: PetscCall(PetscFree(set_a));
426: PetscCall(PetscFree(set_b));
428: PetscFunctionReturn(PETSC_SUCCESS);
429: }
431: /* Tests functionality when setb is small and setb is large */
432: PetscErrorCode test_big_small()
433: {
434: PetscInt64 *set_a, *set_b;
435: PetscInt64 truth[] = {2, 1, 8};
436: PetscMPIInt length = 1;
438: PetscFunctionBeginUser;
440: PetscCall(Cube(&set_a, 999));
441: PetscCall(PetscMalloc1(5, &set_b));
443: set_b[0] = 4;
444: set_b[1] = 1;
445: set_b[2] = 4;
446: set_b[3] = 8;
447: set_b[4] = 9;
449: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
450: PetscCall(PrintSet(set_a));
451: PetscCall(AssertSetsEqual(set_a, truth));
453: PetscCall(PetscFree(set_a));
454: PetscCall(PetscFree(set_b));
456: PetscFunctionReturn(PETSC_SUCCESS);
457: }
459: /* Tests functionality when setb is medium sized and setb is large */
460: PetscErrorCode test_big_moderate()
461: {
462: PetscInt64 *set_a, *set_b;
463: PetscInt64 truth[] = {2, 1, 8};
464: PetscMPIInt length = 1;
466: PetscFunctionBeginUser;
468: PetscCall(Cube(&set_a, 999));
469: PetscCall(Fibonnaci(&set_b, 49));
471: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
472: PetscCall(PrintSet(set_a));
473: PetscCall(AssertSetsEqual(set_a, truth));
475: PetscCall(PetscFree(set_a));
476: PetscCall(PetscFree(set_b));
478: PetscFunctionReturn(PETSC_SUCCESS);
479: }
481: /* Tests functionality when seta and setb are large, in the opposite
482: order to test_big_big() */
483: PetscErrorCode test_big_big_reversed()
484: {
485: PetscInt64 *set_a, *set_b;
486: PetscInt64 *truth;
487: PetscMPIInt length = 1;
489: PetscFunctionBeginUser;
491: PetscCall(Cube(&set_a, 999));
492: PetscCall(Square(&set_b, 999));
494: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
495: PetscCall(PrintSet(set_a));
497: PetscCall(Sixth(&truth, 9));
498: PetscCall(AssertSetsEqual(set_a, truth));
500: PetscCall(PetscFree(set_a));
501: PetscCall(PetscFree(set_b));
502: PetscCall(PetscFree(truth));
504: PetscFunctionReturn(PETSC_SUCCESS);
505: }
507: /* Main executes the individual tests in a predefined order */
508: int main(int argc, char **argv)
509: {
510: PetscFunctionBeginUser;
511: PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
513: /* Small tests */
514: /* Test different edge cases with small sets */
515: PetscCall(test_empty_empty());
516: PetscCall(test_a_empty());
517: PetscCall(test_b_empty());
518: PetscCall(test_identical());
519: PetscCall(test_disjoint());
520: PetscCall(test_single_common());
521: PetscCall(test_issue_1247());
523: /* Big tests */
524: /* Test different edge cases with big sets */
525: PetscCall(test_empty_big());
526: PetscCall(test_small_big());
527: PetscCall(test_moderate_big());
528: PetscCall(test_big_big());
529: PetscCall(test_big_empty());
530: PetscCall(test_big_small());
531: PetscCall(test_big_moderate());
532: PetscCall(test_big_big_reversed());
534: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
535: PetscCall(PetscFinalize());
536: return 0;
537: }
539: /*TEST
541: test:
542: suffix: 0
544: TEST*/