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*/