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] = 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] = 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] = 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] = 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];
79: PetscFunctionBeginUser;
80: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "["));
81: for (PetscInt64 ii = 1; ii <= set[0]; ii++) {
82: PetscCall(PetscFormatConvert(" %" PetscInt64_FMT ",", text));
83: PetscCall(PetscPrintf(PETSC_COMM_WORLD, text, set[ii]));
84: }
85: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "]\n"));
86: PetscFunctionReturn(PETSC_SUCCESS);
87: }
89: /* Check set equality */
90: PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
91: {
92: PetscFunctionBeginUser;
93: PetscAssert(set[0] == true_set[0], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
94: 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");
95: PetscFunctionReturn(PETSC_SUCCESS);
96: }
98: /* Tests functionality when two enpty sets are passed */
99: PetscErrorCode test_empty_empty(void)
100: {
101: PetscInt64 *set_a, *set_b;
102: PetscInt64 truth[] = {0};
103: PetscMPIInt length = 1;
105: PetscFunctionBeginUser;
106: PetscCall(PetscMalloc1(1, &set_a));
107: PetscCall(PetscMalloc1(1, &set_b));
109: set_a[0] = 0;
111: set_b[0] = 0;
113: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
114: PetscCall(PrintSet(set_a));
115: PetscCall(AssertSetsEqual(set_a, truth));
117: PetscCall(PetscFree(set_a));
118: PetscCall(PetscFree(set_b));
119: PetscFunctionReturn(PETSC_SUCCESS);
120: }
122: /* Tests functionality when seta is empty */
123: PetscErrorCode test_a_empty(void)
124: {
125: PetscInt64 *set_a, *set_b;
126: PetscInt64 truth[] = {0};
127: PetscMPIInt length = 1;
129: PetscFunctionBeginUser;
130: PetscCall(PetscMalloc1(1, &set_a));
131: PetscCall(PetscMalloc1(2, &set_b));
133: set_a[0] = 0;
135: set_b[0] = 1;
136: set_b[1] = 1;
138: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
139: PetscCall(PrintSet(set_a));
140: PetscCall(AssertSetsEqual(set_a, truth));
142: PetscCall(PetscFree(set_a));
143: PetscCall(PetscFree(set_b));
144: PetscFunctionReturn(PETSC_SUCCESS);
145: }
147: /* Tests functionality when setb is empty */
148: PetscErrorCode test_b_empty(void)
149: {
150: PetscInt64 *set_a, *set_b;
151: PetscInt64 truth[] = {0};
152: PetscMPIInt length = 1;
154: PetscFunctionBeginUser;
155: PetscCall(PetscMalloc1(2, &set_a));
156: PetscCall(PetscMalloc1(1, &set_b));
158: set_a[0] = 1;
159: set_a[1] = 1;
161: set_b[0] = 0;
163: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
164: PetscCall(PrintSet(set_a));
165: PetscCall(AssertSetsEqual(set_a, truth));
167: PetscCall(PetscFree(set_a));
168: PetscCall(PetscFree(set_b));
169: PetscFunctionReturn(PETSC_SUCCESS);
170: }
172: /* Tests functionality when both sets are identical */
173: PetscErrorCode test_identical(void)
174: {
175: PetscInt64 *set_a, *set_b;
176: PetscInt64 truth[] = {3, 1, 4, 9};
177: PetscMPIInt length = 4;
179: PetscFunctionBeginUser;
180: PetscCall(PetscMalloc1(4, &set_a));
181: PetscCall(PetscMalloc1(4, &set_b));
183: set_a[0] = 3;
184: set_a[1] = 1;
185: set_a[2] = 4;
186: set_a[3] = 9;
188: set_b[0] = 3;
189: set_b[1] = 1;
190: set_b[2] = 4;
191: set_b[3] = 9;
193: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
194: PetscCall(PrintSet(set_a));
195: PetscCall(AssertSetsEqual(set_a, truth));
197: PetscCall(PetscFree(set_a));
198: PetscCall(PetscFree(set_b));
199: PetscFunctionReturn(PETSC_SUCCESS);
200: }
202: /* Tests functionality when sets have no elements in common */
203: PetscErrorCode test_disjoint(void)
204: {
205: PetscInt64 *set_a, *set_b;
206: PetscInt64 truth[] = {0};
207: PetscMPIInt length = 1;
209: PetscFunctionBeginUser;
210: PetscCall(PetscMalloc1(4, &set_a));
211: PetscCall(PetscMalloc1(4, &set_b));
213: set_a[0] = 3;
214: set_a[1] = 1;
215: set_a[2] = 4;
216: set_a[3] = 9;
218: set_b[0] = 3;
219: set_b[1] = 2;
220: set_b[2] = 6;
221: set_b[3] = 8;
223: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
224: PetscCall(PrintSet(set_a));
225: PetscCall(AssertSetsEqual(set_a, truth));
227: PetscCall(PetscFree(set_a));
228: PetscCall(PetscFree(set_b));
229: PetscFunctionReturn(PETSC_SUCCESS);
230: }
232: /* Tests functionality when sets only have one element in common */
233: PetscErrorCode test_single_common(void)
234: {
235: PetscInt64 *set_a, *set_b;
236: PetscInt64 truth[] = {1, 4};
237: PetscMPIInt length = 1;
239: PetscFunctionBeginUser;
240: PetscCall(PetscMalloc1(4, &set_a));
241: PetscCall(PetscMalloc1(5, &set_b));
243: set_a[0] = 3;
244: set_a[1] = 1;
245: set_a[2] = 4;
246: set_a[3] = 9;
248: set_b[0] = 3;
249: set_b[1] = 2;
250: set_b[2] = 4;
251: set_b[3] = 6;
252: set_b[4] = 8;
254: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
255: PetscCall(PrintSet(set_a));
256: PetscCall(AssertSetsEqual(set_a, truth));
258: PetscCall(PetscFree(set_a));
259: PetscCall(PetscFree(set_b));
260: PetscFunctionReturn(PETSC_SUCCESS);
261: }
263: /* Specific test case flagged by PETSc issue #1247 */
264: PetscErrorCode test_issue_1247(void)
265: {
266: PetscInt64 *set_a, *set_b;
267: PetscInt64 truth[] = {0};
268: PetscMPIInt length = 1;
270: PetscFunctionBeginUser;
271: PetscCall(PetscMalloc1(3, &set_a));
272: PetscCall(PetscMalloc1(2, &set_b));
274: set_a[0] = 2;
275: set_a[1] = 2;
276: set_a[2] = 3;
278: set_b[0] = 1;
279: set_b[1] = 1;
281: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
282: PetscCall(PrintSet(set_a));
283: PetscCall(AssertSetsEqual(set_a, truth));
285: PetscCall(PetscFree(set_a));
286: PetscCall(PetscFree(set_b));
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
290: /* Tests functionality when seta is empty and setb is large */
291: PetscErrorCode test_empty_big(void)
292: {
293: PetscInt64 *set_a, *set_b;
294: PetscInt64 truth[] = {0};
295: PetscMPIInt length = 1;
297: PetscFunctionBeginUser;
298: PetscCall(PetscMalloc1(1, &set_a));
299: PetscCall(Square(&set_b, 999));
301: set_a[0] = 0;
303: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
304: PetscCall(PrintSet(set_a));
305: PetscCall(AssertSetsEqual(set_a, truth));
307: PetscCall(PetscFree(set_a));
308: PetscCall(PetscFree(set_b));
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /* Tests functionality when seta is small and setb is large */
313: PetscErrorCode test_small_big(void)
314: {
315: PetscInt64 *set_a, *set_b;
316: PetscInt64 truth[] = {3, 1, 4, 9};
317: PetscMPIInt length = 1;
319: PetscFunctionBeginUser;
320: PetscCall(PetscMalloc1(5, &set_a));
321: PetscCall(Square(&set_b, 999));
323: set_a[0] = 4;
324: set_a[1] = 1;
325: set_a[2] = 4;
326: set_a[3] = 8;
327: set_a[4] = 9;
329: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
330: PetscCall(PrintSet(set_a));
331: PetscCall(AssertSetsEqual(set_a, truth));
333: PetscCall(PetscFree(set_a));
334: PetscCall(PetscFree(set_b));
335: PetscFunctionReturn(PETSC_SUCCESS);
336: }
338: /* Tests functionality when seta is medium sized and setb is large */
339: PetscErrorCode test_moderate_big(void)
340: {
341: PetscInt64 *set_a, *set_b;
342: PetscInt64 truth[] = {2, 1, 144};
343: PetscMPIInt length = 1;
345: PetscFunctionBeginUser;
346: PetscCall(Fibonnaci(&set_a, 49));
347: PetscCall(Square(&set_b, 999));
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));
355: PetscFunctionReturn(PETSC_SUCCESS);
356: }
358: /* Tests functionality when seta and setb are large */
359: PetscErrorCode test_big_big(void)
360: {
361: PetscInt64 *set_a, *set_b;
362: PetscInt64 *truth;
363: PetscMPIInt length = 1;
365: PetscFunctionBeginUser;
366: PetscCall(Cube(&set_a, 999));
367: PetscCall(Square(&set_b, 999));
369: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
370: PetscCall(PrintSet(set_a));
372: PetscCall(Sixth(&truth, 9));
373: PetscCall(AssertSetsEqual(set_a, truth));
375: PetscCall(PetscFree(set_a));
376: PetscCall(PetscFree(set_b));
377: PetscCall(PetscFree(truth));
378: PetscFunctionReturn(PETSC_SUCCESS);
379: }
381: /* Tests functionality when setb is empty and setb is large */
382: PetscErrorCode test_big_empty(void)
383: {
384: PetscInt64 *set_a, *set_b;
385: PetscInt64 truth[] = {0};
386: PetscMPIInt length = 1;
388: PetscFunctionBeginUser;
389: PetscCall(Cube(&set_a, 999));
390: PetscCall(PetscMalloc1(1, &set_b));
392: set_b[0] = 0;
394: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
395: PetscCall(PrintSet(set_a));
396: PetscCall(AssertSetsEqual(set_a, truth));
398: PetscCall(PetscFree(set_a));
399: PetscCall(PetscFree(set_b));
400: PetscFunctionReturn(PETSC_SUCCESS);
401: }
403: /* Tests functionality when setb is small and setb is large */
404: PetscErrorCode test_big_small(void)
405: {
406: PetscInt64 *set_a, *set_b;
407: PetscInt64 truth[] = {2, 1, 8};
408: PetscMPIInt length = 1;
410: PetscFunctionBeginUser;
411: PetscCall(Cube(&set_a, 999));
412: PetscCall(PetscMalloc1(5, &set_b));
414: set_b[0] = 4;
415: set_b[1] = 1;
416: set_b[2] = 4;
417: set_b[3] = 8;
418: set_b[4] = 9;
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));
426: PetscFunctionReturn(PETSC_SUCCESS);
427: }
429: /* Tests functionality when setb is medium sized and setb is large */
430: PetscErrorCode test_big_moderate(void)
431: {
432: PetscInt64 *set_a, *set_b;
433: PetscInt64 truth[] = {2, 1, 8};
434: PetscMPIInt length = 1;
436: PetscFunctionBeginUser;
437: PetscCall(Cube(&set_a, 999));
438: PetscCall(Fibonnaci(&set_b, 49));
440: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
441: PetscCall(PrintSet(set_a));
442: PetscCall(AssertSetsEqual(set_a, truth));
444: PetscCall(PetscFree(set_a));
445: PetscCall(PetscFree(set_b));
446: PetscFunctionReturn(PETSC_SUCCESS);
447: }
449: /* Tests functionality when seta and setb are large, in the opposite
450: order to test_big_big() */
451: PetscErrorCode test_big_big_reversed(void)
452: {
453: PetscInt64 *set_a, *set_b;
454: PetscInt64 *truth;
455: PetscMPIInt length = 1;
457: PetscFunctionBeginUser;
458: PetscCall(Cube(&set_a, 999));
459: PetscCall(Square(&set_b, 999));
461: PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
462: PetscCall(PrintSet(set_a));
464: PetscCall(Sixth(&truth, 9));
465: PetscCall(AssertSetsEqual(set_a, truth));
467: PetscCall(PetscFree(set_a));
468: PetscCall(PetscFree(set_b));
469: PetscCall(PetscFree(truth));
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: /* Main executes the individual tests in a predefined order */
474: int main(int argc, char **argv)
475: {
476: PetscFunctionBeginUser;
477: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
479: /* Small tests */
480: /* Test different edge cases with small sets */
481: PetscCall(test_empty_empty());
482: PetscCall(test_a_empty());
483: PetscCall(test_b_empty());
484: PetscCall(test_identical());
485: PetscCall(test_disjoint());
486: PetscCall(test_single_common());
487: PetscCall(test_issue_1247());
489: /* Big tests */
490: /* Test different edge cases with big sets */
491: PetscCall(test_empty_big());
492: PetscCall(test_small_big());
493: PetscCall(test_moderate_big());
494: PetscCall(test_big_big());
495: PetscCall(test_big_empty());
496: PetscCall(test_big_small());
497: PetscCall(test_big_moderate());
498: PetscCall(test_big_big_reversed());
500: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
501: PetscCall(PetscFinalize());
502: return 0;
503: }
505: /*TEST
507: test:
508: suffix: 0
510: TEST*/