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