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\n");
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;
110: PetscCall(PetscMalloc1(1, &set_a));
111: PetscCall(PetscMalloc1(1, &set_b));
113: set_a[0] = 0;
115: set_b[0] = 0;
117: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
118: PetscCall(PrintSet(set_a));
119: PetscCall(AssertSetsEqual(set_a, truth));
121: PetscCall(PetscFree(set_a));
122: PetscCall(PetscFree(set_b));
124: PetscFunctionReturn(PETSC_SUCCESS);
125: }
127: /* Tests functionality when seta is empty */
128: PetscErrorCode test_a_empty()
129: {
130: PetscInt64 *set_a, *set_b;
131: PetscInt64 truth[] = {0};
132: PetscMPIInt length = 1;
134: PetscFunctionBeginUser;
136: PetscCall(PetscMalloc1(1, &set_a));
137: PetscCall(PetscMalloc1(2, &set_b));
139: set_a[0] = 0;
141: set_b[0] = 1;
142: set_b[1] = 1;
144: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
145: PetscCall(PrintSet(set_a));
146: PetscCall(AssertSetsEqual(set_a, truth));
148: PetscCall(PetscFree(set_a));
149: PetscCall(PetscFree(set_b));
151: PetscFunctionReturn(PETSC_SUCCESS);
152: }
154: /* Tests functionality when setb is empty */
155: PetscErrorCode test_b_empty()
156: {
157: PetscInt64 *set_a, *set_b;
158: PetscInt64 truth[] = {0};
159: PetscMPIInt length = 1;
161: PetscFunctionBeginUser;
163: PetscCall(PetscMalloc1(2, &set_a));
164: PetscCall(PetscMalloc1(1, &set_b));
166: set_a[0] = 1;
167: set_a[1] = 1;
169: set_b[0] = 0;
171: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
172: PetscCall(PrintSet(set_a));
173: PetscCall(AssertSetsEqual(set_a, truth));
175: PetscCall(PetscFree(set_a));
176: PetscCall(PetscFree(set_b));
178: PetscFunctionReturn(PETSC_SUCCESS);
179: }
181: /* Tests functionality when both sets are identical */
182: PetscErrorCode test_identical()
183: {
184: PetscInt64 *set_a, *set_b;
185: PetscInt64 truth[] = {3, 1, 4, 9};
186: PetscMPIInt length = 4;
188: PetscFunctionBeginUser;
190: PetscCall(PetscMalloc1(4, &set_a));
191: PetscCall(PetscMalloc1(4, &set_b));
193: set_a[0] = 3;
194: set_a[1] = 1;
195: set_a[2] = 4;
196: set_a[3] = 9;
198: set_b[0] = 3;
199: set_b[1] = 1;
200: set_b[2] = 4;
201: set_b[3] = 9;
203: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
204: PetscCall(PrintSet(set_a));
205: PetscCall(AssertSetsEqual(set_a, truth));
207: PetscCall(PetscFree(set_a));
208: PetscCall(PetscFree(set_b));
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /* Tests functionality when sets have no elements in common */
214: PetscErrorCode test_disjoint()
215: {
216: PetscInt64 *set_a, *set_b;
217: PetscInt64 truth[] = {0};
218: PetscMPIInt length = 1;
220: PetscFunctionBeginUser;
222: PetscCall(PetscMalloc1(4, &set_a));
223: PetscCall(PetscMalloc1(4, &set_b));
225: set_a[0] = 3;
226: set_a[1] = 1;
227: set_a[2] = 4;
228: set_a[3] = 9;
230: set_b[0] = 3;
231: set_b[1] = 2;
232: set_b[2] = 6;
233: set_b[3] = 8;
235: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
236: PetscCall(PrintSet(set_a));
237: PetscCall(AssertSetsEqual(set_a, truth));
239: PetscCall(PetscFree(set_a));
240: PetscCall(PetscFree(set_b));
242: PetscFunctionReturn(PETSC_SUCCESS);
243: }
245: /* Tests functionality when sets only have one element in common */
246: PetscErrorCode test_single_common()
247: {
248: PetscInt64 *set_a, *set_b;
249: PetscInt64 truth[] = {1, 4};
250: PetscMPIInt length = 1;
252: PetscFunctionBeginUser;
254: PetscCall(PetscMalloc1(4, &set_a));
255: PetscCall(PetscMalloc1(5, &set_b));
257: set_a[0] = 3;
258: set_a[1] = 1;
259: set_a[2] = 4;
260: set_a[3] = 9;
262: set_b[0] = 3;
263: set_b[1] = 2;
264: set_b[2] = 4;
265: set_b[3] = 6;
266: set_b[4] = 8;
268: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
269: PetscCall(PrintSet(set_a));
270: PetscCall(AssertSetsEqual(set_a, truth));
272: PetscCall(PetscFree(set_a));
273: PetscCall(PetscFree(set_b));
275: PetscFunctionReturn(PETSC_SUCCESS);
276: }
278: /* Specific test case flagged by PETSc issue #1247 */
279: PetscErrorCode test_issue_1247()
280: {
281: PetscInt64 *set_a, *set_b;
282: PetscInt64 truth[] = {0};
283: PetscMPIInt length = 1;
285: PetscFunctionBeginUser;
287: PetscCall(PetscMalloc1(3, &set_a));
288: PetscCall(PetscMalloc1(2, &set_b));
290: set_a[0] = 2;
291: set_a[1] = 2;
292: set_a[2] = 3;
294: set_b[0] = 1;
295: set_b[1] = 1;
297: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
298: PetscCall(PrintSet(set_a));
299: PetscCall(AssertSetsEqual(set_a, truth));
301: PetscCall(PetscFree(set_a));
302: PetscCall(PetscFree(set_b));
304: PetscFunctionReturn(PETSC_SUCCESS);
305: }
307: /* Tests functionality when seta is empty and setb is large */
308: PetscErrorCode test_empty_big()
309: {
310: PetscInt64 *set_a, *set_b;
311: PetscInt64 truth[] = {0};
312: PetscMPIInt length = 1;
314: PetscFunctionBeginUser;
316: PetscCall(PetscMalloc1(1, &set_a));
317: PetscCall(Square(&set_b, 999));
319: set_a[0] = 0;
321: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
322: PetscCall(PrintSet(set_a));
323: PetscCall(AssertSetsEqual(set_a, truth));
325: PetscCall(PetscFree(set_a));
326: PetscCall(PetscFree(set_b));
328: PetscFunctionReturn(PETSC_SUCCESS);
329: }
331: /* Tests functionality when seta is small and setb is large */
332: PetscErrorCode test_small_big()
333: {
334: PetscInt64 *set_a, *set_b;
335: PetscInt64 truth[] = {3, 1, 4, 9};
336: PetscMPIInt length = 1;
338: PetscFunctionBeginUser;
340: PetscCall(PetscMalloc1(5, &set_a));
341: PetscCall(Square(&set_b, 999));
343: set_a[0] = 4;
344: set_a[1] = 1;
345: set_a[2] = 4;
346: set_a[3] = 8;
347: set_a[4] = 9;
349: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
350: PetscCall(PrintSet(set_a));
351: PetscCall(AssertSetsEqual(set_a, truth));
353: PetscCall(PetscFree(set_a));
354: PetscCall(PetscFree(set_b));
356: PetscFunctionReturn(PETSC_SUCCESS);
357: }
359: /* Tests functionality when seta is medium sized and setb is large */
360: PetscErrorCode test_moderate_big()
361: {
362: PetscInt64 *set_a, *set_b;
363: PetscInt64 truth[] = {2, 1, 144};
364: PetscMPIInt length = 1;
366: PetscFunctionBeginUser;
368: PetscCall(Fibonnaci(&set_a, 49));
369: PetscCall(Square(&set_b, 999));
371: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
372: PetscCall(PrintSet(set_a));
373: PetscCall(AssertSetsEqual(set_a, truth));
375: PetscCall(PetscFree(set_a));
376: PetscCall(PetscFree(set_b));
378: PetscFunctionReturn(PETSC_SUCCESS);
379: }
381: /* Tests functionality when seta and setb are large */
382: PetscErrorCode test_big_big()
383: {
384: PetscInt64 *set_a, *set_b;
385: PetscInt64 *truth;
386: PetscMPIInt length = 1;
388: PetscFunctionBeginUser;
390: PetscCall(Cube(&set_a, 999));
391: PetscCall(Square(&set_b, 999));
393: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
394: PetscCall(PrintSet(set_a));
396: PetscCall(Sixth(&truth, 9));
397: PetscCall(AssertSetsEqual(set_a, truth));
399: PetscCall(PetscFree(set_a));
400: PetscCall(PetscFree(set_b));
401: PetscCall(PetscFree(truth));
403: PetscFunctionReturn(PETSC_SUCCESS);
404: }
406: /* Tests functionality when setb is empty and setb is large */
407: PetscErrorCode test_big_empty()
408: {
409: PetscInt64 *set_a, *set_b;
410: PetscInt64 truth[] = {0};
411: PetscMPIInt length = 1;
413: PetscFunctionBeginUser;
415: PetscCall(Cube(&set_a, 999));
416: PetscCall(PetscMalloc1(1, &set_b));
418: set_b[0] = 0;
420: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
421: PetscCall(PrintSet(set_a));
422: PetscCall(AssertSetsEqual(set_a, truth));
424: PetscCall(PetscFree(set_a));
425: PetscCall(PetscFree(set_b));
427: PetscFunctionReturn(PETSC_SUCCESS);
428: }
430: /* Tests functionality when setb is small and setb is large */
431: PetscErrorCode test_big_small()
432: {
433: PetscInt64 *set_a, *set_b;
434: PetscInt64 truth[] = {2, 1, 8};
435: PetscMPIInt length = 1;
437: PetscFunctionBeginUser;
439: PetscCall(Cube(&set_a, 999));
440: PetscCall(PetscMalloc1(5, &set_b));
442: set_b[0] = 4;
443: set_b[1] = 1;
444: set_b[2] = 4;
445: set_b[3] = 8;
446: set_b[4] = 9;
448: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
449: PetscCall(PrintSet(set_a));
450: PetscCall(AssertSetsEqual(set_a, truth));
452: PetscCall(PetscFree(set_a));
453: PetscCall(PetscFree(set_b));
455: PetscFunctionReturn(PETSC_SUCCESS);
456: }
458: /* Tests functionality when setb is medium sized and setb is large */
459: PetscErrorCode test_big_moderate()
460: {
461: PetscInt64 *set_a, *set_b;
462: PetscInt64 truth[] = {2, 1, 8};
463: PetscMPIInt length = 1;
465: PetscFunctionBeginUser;
467: PetscCall(Cube(&set_a, 999));
468: PetscCall(Fibonnaci(&set_b, 49));
470: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
471: PetscCall(PrintSet(set_a));
472: PetscCall(AssertSetsEqual(set_a, truth));
474: PetscCall(PetscFree(set_a));
475: PetscCall(PetscFree(set_b));
477: PetscFunctionReturn(PETSC_SUCCESS);
478: }
480: /* Tests functionality when seta and setb are large, in the opposite
481: order to test_big_big() */
482: PetscErrorCode test_big_big_reversed()
483: {
484: PetscInt64 *set_a, *set_b;
485: PetscInt64 *truth;
486: PetscMPIInt length = 1;
488: PetscFunctionBeginUser;
490: PetscCall(Cube(&set_a, 999));
491: PetscCall(Square(&set_b, 999));
493: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
494: PetscCall(PrintSet(set_a));
496: PetscCall(Sixth(&truth, 9));
497: PetscCall(AssertSetsEqual(set_a, truth));
499: PetscCall(PetscFree(set_a));
500: PetscCall(PetscFree(set_b));
501: PetscCall(PetscFree(truth));
503: PetscFunctionReturn(PETSC_SUCCESS);
504: }
506: /* Main executes the individual tests in a predefined order */
507: int main(int argc, char **argv)
508: {
509: PetscFunctionBeginUser;
510: PetscCall(PetscInitialize(&argc, &argv, (char *)0, help));
512: /* Small tests */
513: /* Test different edge cases with small sets */
514: PetscCall(test_empty_empty());
515: PetscCall(test_a_empty());
516: PetscCall(test_b_empty());
517: PetscCall(test_identical());
518: PetscCall(test_disjoint());
519: PetscCall(test_single_common());
520: PetscCall(test_issue_1247());
522: /* Big tests */
523: /* Test different edge cases with big sets */
524: PetscCall(test_empty_big());
525: PetscCall(test_small_big());
526: PetscCall(test_moderate_big());
527: PetscCall(test_big_big());
528: PetscCall(test_big_empty());
529: PetscCall(test_big_small());
530: PetscCall(test_big_moderate());
531: PetscCall(test_big_big_reversed());
533: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
534: PetscCall(PetscFinalize());
535: return 0;
536: }
538: /*TEST
540: test:
541: suffix: 0
543: TEST*/