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