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};

 32:   PetscAssert((n < 50), PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "n must be less than 50\n");
 33:   PetscMalloc1(n + 1, set);
 34:   (*set)[0] = (PetscInt64)n;
 35:   for (ii = 0; ii < n; ii++) { (*set)[ii + 1] = fib[ii]; }
 36:   return 0;
 37: }

 39: /* Populate a set with Square numbers */
 40: PetscErrorCode Square(PetscInt64 **set, PetscInt n)
 41: {
 42:   PetscInt64 ii;

 45:   PetscMalloc1(n + 1, set);
 46:   (*set)[0] = (PetscInt64)n;
 47:   for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii; }
 48:   return 0;
 49: }

 51: /* Populate a set with Cube numbers */
 52: PetscErrorCode Cube(PetscInt64 **set, PetscInt n)
 53: {
 54:   PetscInt64 ii;

 57:   PetscMalloc1(n + 1, set);
 58:   (*set)[0] = (PetscInt64)n;
 59:   for (ii = 1; ii < n + 1; ii++) { (*set)[ii] = ii * ii * ii; }
 60:   return 0;
 61: }

 63: /* Populate a set with numbers to sixth power */
 64: PetscErrorCode Sixth(PetscInt64 **set, PetscInt n)
 65: {
 66:   PetscInt64 ii;

 69:   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:   return 0;
 73: }

 75: /* Print out the contents of a set */
 76: PetscErrorCode PrintSet(PetscInt64 *set)
 77: {
 78:   char     text[64];
 79:   PetscInt ii;

 82:   PetscPrintf(PETSC_COMM_WORLD, "[");
 83:   for (ii = 1; ii <= (PetscInt)set[0]; ii++) {
 84:     PetscFormatConvert(" %" PetscInt64_FMT ",", text);
 85:     PetscPrintf(PETSC_COMM_WORLD, text, set[ii]);
 86:   }
 87:   PetscPrintf(PETSC_COMM_WORLD, "]\n");
 88:   return 0;
 89: }

 91: /* Check set equality */
 92: PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
 93: {
 94:   PetscInt ii;

 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:   return 0;
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;


111:   PetscMalloc1(1, &set_a);
112:   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:   PrintSet(set_a);
120:   AssertSetsEqual(set_a, truth);

122:   PetscFree(set_a);
123:   PetscFree(set_b);

125:   return 0;
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;


137:   PetscMalloc1(1, &set_a);
138:   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:   PrintSet(set_a);
147:   AssertSetsEqual(set_a, truth);

149:   PetscFree(set_a);
150:   PetscFree(set_b);

152:   return 0;
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;


164:   PetscMalloc1(2, &set_a);
165:   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:   PrintSet(set_a);
174:   AssertSetsEqual(set_a, truth);

176:   PetscFree(set_a);
177:   PetscFree(set_b);

179:   return 0;
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;


191:   PetscMalloc1(4, &set_a);
192:   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:   PrintSet(set_a);
206:   AssertSetsEqual(set_a, truth);

208:   PetscFree(set_a);
209:   PetscFree(set_b);

211:   return 0;
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;


223:   PetscMalloc1(4, &set_a);
224:   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:   PrintSet(set_a);
238:   AssertSetsEqual(set_a, truth);

240:   PetscFree(set_a);
241:   PetscFree(set_b);

243:   return 0;
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;


255:   PetscMalloc1(4, &set_a);
256:   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:   PrintSet(set_a);
271:   AssertSetsEqual(set_a, truth);

273:   PetscFree(set_a);
274:   PetscFree(set_b);

276:   return 0;
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;


288:   PetscMalloc1(3, &set_a);
289:   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:   PrintSet(set_a);
300:   AssertSetsEqual(set_a, truth);

302:   PetscFree(set_a);
303:   PetscFree(set_b);

305:   return 0;
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;


317:   PetscMalloc1(1, &set_a);
318:   Square(&set_b, 999);

320:   set_a[0] = 0;

322:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
323:   PrintSet(set_a);
324:   AssertSetsEqual(set_a, truth);

326:   PetscFree(set_a);
327:   PetscFree(set_b);

329:   return 0;
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;


341:   PetscMalloc1(5, &set_a);
342:   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:   PrintSet(set_a);
352:   AssertSetsEqual(set_a, truth);

354:   PetscFree(set_a);
355:   PetscFree(set_b);

357:   return 0;
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;


369:   Fibonnaci(&set_a, 49);
370:   Square(&set_b, 999);

372:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
373:   PrintSet(set_a);
374:   AssertSetsEqual(set_a, truth);

376:   PetscFree(set_a);
377:   PetscFree(set_b);

379:   return 0;
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;


391:   Cube(&set_a, 999);
392:   Square(&set_b, 999);

394:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
395:   PrintSet(set_a);

397:   Sixth(&truth, 9);
398:   AssertSetsEqual(set_a, truth);

400:   PetscFree(set_a);
401:   PetscFree(set_b);
402:   PetscFree(truth);

404:   return 0;
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;


416:   Cube(&set_a, 999);
417:   PetscMalloc1(1, &set_b);

419:   set_b[0] = 0;

421:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
422:   PrintSet(set_a);
423:   AssertSetsEqual(set_a, truth);

425:   PetscFree(set_a);
426:   PetscFree(set_b);

428:   return 0;
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;


440:   Cube(&set_a, 999);
441:   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:   PrintSet(set_a);
451:   AssertSetsEqual(set_a, truth);

453:   PetscFree(set_a);
454:   PetscFree(set_b);

456:   return 0;
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;


468:   Cube(&set_a, 999);
469:   Fibonnaci(&set_b, 49);

471:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
472:   PrintSet(set_a);
473:   AssertSetsEqual(set_a, truth);

475:   PetscFree(set_a);
476:   PetscFree(set_b);

478:   return 0;
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;


491:   Cube(&set_a, 999);
492:   Square(&set_b, 999);

494:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
495:   PrintSet(set_a);

497:   Sixth(&truth, 9);
498:   AssertSetsEqual(set_a, truth);

500:   PetscFree(set_a);
501:   PetscFree(set_b);
502:   PetscFree(truth);

504:   return 0;
505: }

507: /* Main executes the individual tests in a predefined order */
508: int main(int argc, char **argv)
509: {
511:   PetscInitialize(&argc, &argv, (char *)0, help);

513:   /* Small tests */
514:   /* Test different edge cases with small sets */
515:   test_empty_empty();
516:   test_a_empty();
517:   test_b_empty();
518:   test_identical();
519:   test_disjoint();
520:   test_single_common();
521:   test_issue_1247();

523:   /* Big tests */
524:   /* Test different edge cases with big sets */
525:   test_empty_big();
526:   test_small_big();
527:   test_moderate_big();
528:   test_big_big();
529:   test_big_empty();
530:   test_big_small();
531:   test_big_moderate();
532:   test_big_big_reversed();

534:   PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n");
535:   PetscFinalize();
536:   return 0;
537: }

539: /*TEST

541:    test:
542:      output_file: output/ex62.out

544: TEST*/