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] = (PetscInt64)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] = (PetscInt64)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] = (PetscInt64)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] = (PetscInt64)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];
 78:   PetscInt ii;

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

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

 95:   PetscFunctionBeginUser;
 96:   PetscAssert(set[0] == true_set[0], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
 97:   for (ii = 1; ii < set[0] + 1; ii++) PetscAssert(set[ii] == true_set[ii], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets are different");
 98:   PetscFunctionReturn(PETSC_SUCCESS);
 99: }

101: /* Tests functionality when two enpty sets are passed */
102: PetscErrorCode test_empty_empty()
103: {
104:   PetscInt64 *set_a, *set_b;
105:   PetscInt64  truth[] = {0};
106:   PetscMPIInt length  = 1;

108:   PetscFunctionBeginUser;
109:   PetscCall(PetscMalloc1(1, &set_a));
110:   PetscCall(PetscMalloc1(1, &set_b));

112:   set_a[0] = 0;

114:   set_b[0] = 0;

116:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
117:   PetscCall(PrintSet(set_a));
118:   PetscCall(AssertSetsEqual(set_a, truth));

120:   PetscCall(PetscFree(set_a));
121:   PetscCall(PetscFree(set_b));
122:   PetscFunctionReturn(PETSC_SUCCESS);
123: }

125: /* Tests functionality when seta is empty */
126: PetscErrorCode test_a_empty()
127: {
128:   PetscInt64 *set_a, *set_b;
129:   PetscInt64  truth[] = {0};
130:   PetscMPIInt length  = 1;

132:   PetscFunctionBeginUser;
133:   PetscCall(PetscMalloc1(1, &set_a));
134:   PetscCall(PetscMalloc1(2, &set_b));

136:   set_a[0] = 0;

138:   set_b[0] = 1;
139:   set_b[1] = 1;

141:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
142:   PetscCall(PrintSet(set_a));
143:   PetscCall(AssertSetsEqual(set_a, truth));

145:   PetscCall(PetscFree(set_a));
146:   PetscCall(PetscFree(set_b));
147:   PetscFunctionReturn(PETSC_SUCCESS);
148: }

150: /* Tests functionality when setb is empty */
151: PetscErrorCode test_b_empty()
152: {
153:   PetscInt64 *set_a, *set_b;
154:   PetscInt64  truth[] = {0};
155:   PetscMPIInt length  = 1;

157:   PetscFunctionBeginUser;
158:   PetscCall(PetscMalloc1(2, &set_a));
159:   PetscCall(PetscMalloc1(1, &set_b));

161:   set_a[0] = 1;
162:   set_a[1] = 1;

164:   set_b[0] = 0;

166:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
167:   PetscCall(PrintSet(set_a));
168:   PetscCall(AssertSetsEqual(set_a, truth));

170:   PetscCall(PetscFree(set_a));
171:   PetscCall(PetscFree(set_b));
172:   PetscFunctionReturn(PETSC_SUCCESS);
173: }

175: /* Tests functionality when both sets are identical */
176: PetscErrorCode test_identical()
177: {
178:   PetscInt64 *set_a, *set_b;
179:   PetscInt64  truth[] = {3, 1, 4, 9};
180:   PetscMPIInt length  = 4;

182:   PetscFunctionBeginUser;
183:   PetscCall(PetscMalloc1(4, &set_a));
184:   PetscCall(PetscMalloc1(4, &set_b));

186:   set_a[0] = 3;
187:   set_a[1] = 1;
188:   set_a[2] = 4;
189:   set_a[3] = 9;

191:   set_b[0] = 3;
192:   set_b[1] = 1;
193:   set_b[2] = 4;
194:   set_b[3] = 9;

196:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
197:   PetscCall(PrintSet(set_a));
198:   PetscCall(AssertSetsEqual(set_a, truth));

200:   PetscCall(PetscFree(set_a));
201:   PetscCall(PetscFree(set_b));
202:   PetscFunctionReturn(PETSC_SUCCESS);
203: }

205: /* Tests functionality when sets have no elements in common */
206: PetscErrorCode test_disjoint()
207: {
208:   PetscInt64 *set_a, *set_b;
209:   PetscInt64  truth[] = {0};
210:   PetscMPIInt length  = 1;

212:   PetscFunctionBeginUser;
213:   PetscCall(PetscMalloc1(4, &set_a));
214:   PetscCall(PetscMalloc1(4, &set_b));

216:   set_a[0] = 3;
217:   set_a[1] = 1;
218:   set_a[2] = 4;
219:   set_a[3] = 9;

221:   set_b[0] = 3;
222:   set_b[1] = 2;
223:   set_b[2] = 6;
224:   set_b[3] = 8;

226:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
227:   PetscCall(PrintSet(set_a));
228:   PetscCall(AssertSetsEqual(set_a, truth));

230:   PetscCall(PetscFree(set_a));
231:   PetscCall(PetscFree(set_b));
232:   PetscFunctionReturn(PETSC_SUCCESS);
233: }

235: /* Tests functionality when sets only have one element in common */
236: PetscErrorCode test_single_common()
237: {
238:   PetscInt64 *set_a, *set_b;
239:   PetscInt64  truth[] = {1, 4};
240:   PetscMPIInt length  = 1;

242:   PetscFunctionBeginUser;
243:   PetscCall(PetscMalloc1(4, &set_a));
244:   PetscCall(PetscMalloc1(5, &set_b));

246:   set_a[0] = 3;
247:   set_a[1] = 1;
248:   set_a[2] = 4;
249:   set_a[3] = 9;

251:   set_b[0] = 3;
252:   set_b[1] = 2;
253:   set_b[2] = 4;
254:   set_b[3] = 6;
255:   set_b[4] = 8;

257:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
258:   PetscCall(PrintSet(set_a));
259:   PetscCall(AssertSetsEqual(set_a, truth));

261:   PetscCall(PetscFree(set_a));
262:   PetscCall(PetscFree(set_b));
263:   PetscFunctionReturn(PETSC_SUCCESS);
264: }

266: /* Specific test case flagged by PETSc issue #1247 */
267: PetscErrorCode test_issue_1247()
268: {
269:   PetscInt64 *set_a, *set_b;
270:   PetscInt64  truth[] = {0};
271:   PetscMPIInt length  = 1;

273:   PetscFunctionBeginUser;
274:   PetscCall(PetscMalloc1(3, &set_a));
275:   PetscCall(PetscMalloc1(2, &set_b));

277:   set_a[0] = 2;
278:   set_a[1] = 2;
279:   set_a[2] = 3;

281:   set_b[0] = 1;
282:   set_b[1] = 1;

284:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
285:   PetscCall(PrintSet(set_a));
286:   PetscCall(AssertSetsEqual(set_a, truth));

288:   PetscCall(PetscFree(set_a));
289:   PetscCall(PetscFree(set_b));
290:   PetscFunctionReturn(PETSC_SUCCESS);
291: }

293: /* Tests functionality when seta is empty and setb is large */
294: PetscErrorCode test_empty_big()
295: {
296:   PetscInt64 *set_a, *set_b;
297:   PetscInt64  truth[] = {0};
298:   PetscMPIInt length  = 1;

300:   PetscFunctionBeginUser;
301:   PetscCall(PetscMalloc1(1, &set_a));
302:   PetscCall(Square(&set_b, 999));

304:   set_a[0] = 0;

306:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
307:   PetscCall(PrintSet(set_a));
308:   PetscCall(AssertSetsEqual(set_a, truth));

310:   PetscCall(PetscFree(set_a));
311:   PetscCall(PetscFree(set_b));
312:   PetscFunctionReturn(PETSC_SUCCESS);
313: }

315: /* Tests functionality when seta is small and setb is large */
316: PetscErrorCode test_small_big()
317: {
318:   PetscInt64 *set_a, *set_b;
319:   PetscInt64  truth[] = {3, 1, 4, 9};
320:   PetscMPIInt length  = 1;

322:   PetscFunctionBeginUser;
323:   PetscCall(PetscMalloc1(5, &set_a));
324:   PetscCall(Square(&set_b, 999));

326:   set_a[0] = 4;
327:   set_a[1] = 1;
328:   set_a[2] = 4;
329:   set_a[3] = 8;
330:   set_a[4] = 9;

332:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
333:   PetscCall(PrintSet(set_a));
334:   PetscCall(AssertSetsEqual(set_a, truth));

336:   PetscCall(PetscFree(set_a));
337:   PetscCall(PetscFree(set_b));
338:   PetscFunctionReturn(PETSC_SUCCESS);
339: }

341: /* Tests functionality when seta is medium sized and setb is large */
342: PetscErrorCode test_moderate_big()
343: {
344:   PetscInt64 *set_a, *set_b;
345:   PetscInt64  truth[] = {2, 1, 144};
346:   PetscMPIInt length  = 1;

348:   PetscFunctionBeginUser;
349:   PetscCall(Fibonnaci(&set_a, 49));
350:   PetscCall(Square(&set_b, 999));

352:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
353:   PetscCall(PrintSet(set_a));
354:   PetscCall(AssertSetsEqual(set_a, truth));

356:   PetscCall(PetscFree(set_a));
357:   PetscCall(PetscFree(set_b));
358:   PetscFunctionReturn(PETSC_SUCCESS);
359: }

361: /* Tests functionality when seta and setb are large */
362: PetscErrorCode test_big_big()
363: {
364:   PetscInt64 *set_a, *set_b;
365:   PetscInt64 *truth;
366:   PetscMPIInt length = 1;

368:   PetscFunctionBeginUser;
369:   PetscCall(Cube(&set_a, 999));
370:   PetscCall(Square(&set_b, 999));

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

375:   PetscCall(Sixth(&truth, 9));
376:   PetscCall(AssertSetsEqual(set_a, truth));

378:   PetscCall(PetscFree(set_a));
379:   PetscCall(PetscFree(set_b));
380:   PetscCall(PetscFree(truth));
381:   PetscFunctionReturn(PETSC_SUCCESS);
382: }

384: /* Tests functionality when setb is empty and setb is large */
385: PetscErrorCode test_big_empty()
386: {
387:   PetscInt64 *set_a, *set_b;
388:   PetscInt64  truth[] = {0};
389:   PetscMPIInt length  = 1;

391:   PetscFunctionBeginUser;
392:   PetscCall(Cube(&set_a, 999));
393:   PetscCall(PetscMalloc1(1, &set_b));

395:   set_b[0] = 0;

397:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
398:   PetscCall(PrintSet(set_a));
399:   PetscCall(AssertSetsEqual(set_a, truth));

401:   PetscCall(PetscFree(set_a));
402:   PetscCall(PetscFree(set_b));
403:   PetscFunctionReturn(PETSC_SUCCESS);
404: }

406: /* Tests functionality when setb is small and setb is large */
407: PetscErrorCode test_big_small()
408: {
409:   PetscInt64 *set_a, *set_b;
410:   PetscInt64  truth[] = {2, 1, 8};
411:   PetscMPIInt length  = 1;

413:   PetscFunctionBeginUser;
414:   PetscCall(Cube(&set_a, 999));
415:   PetscCall(PetscMalloc1(5, &set_b));

417:   set_b[0] = 4;
418:   set_b[1] = 1;
419:   set_b[2] = 4;
420:   set_b[3] = 8;
421:   set_b[4] = 9;

423:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
424:   PetscCall(PrintSet(set_a));
425:   PetscCall(AssertSetsEqual(set_a, truth));

427:   PetscCall(PetscFree(set_a));
428:   PetscCall(PetscFree(set_b));
429:   PetscFunctionReturn(PETSC_SUCCESS);
430: }

432: /* Tests functionality when setb is medium sized and setb is large */
433: PetscErrorCode test_big_moderate()
434: {
435:   PetscInt64 *set_a, *set_b;
436:   PetscInt64  truth[] = {2, 1, 8};
437:   PetscMPIInt length  = 1;

439:   PetscFunctionBeginUser;
440:   PetscCall(Cube(&set_a, 999));
441:   PetscCall(Fibonnaci(&set_b, 49));

443:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
444:   PetscCall(PrintSet(set_a));
445:   PetscCall(AssertSetsEqual(set_a, truth));

447:   PetscCall(PetscFree(set_a));
448:   PetscCall(PetscFree(set_b));
449:   PetscFunctionReturn(PETSC_SUCCESS);
450: }

452: /* Tests functionality when seta and setb are large, in the opposite
453:  order to test_big_big() */
454: PetscErrorCode test_big_big_reversed()
455: {
456:   PetscInt64 *set_a, *set_b;
457:   PetscInt64 *truth;
458:   PetscMPIInt length = 1;

460:   PetscFunctionBeginUser;
461:   PetscCall(Cube(&set_a, 999));
462:   PetscCall(Square(&set_b, 999));

464:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
465:   PetscCall(PrintSet(set_a));

467:   PetscCall(Sixth(&truth, 9));
468:   PetscCall(AssertSetsEqual(set_a, truth));

470:   PetscCall(PetscFree(set_a));
471:   PetscCall(PetscFree(set_b));
472:   PetscCall(PetscFree(truth));
473:   PetscFunctionReturn(PETSC_SUCCESS);
474: }

476: /* Main executes the individual tests in a predefined order */
477: int main(int argc, char **argv)
478: {
479:   PetscFunctionBeginUser;
480:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));

482:   /* Small tests */
483:   /* Test different edge cases with small sets */
484:   PetscCall(test_empty_empty());
485:   PetscCall(test_a_empty());
486:   PetscCall(test_b_empty());
487:   PetscCall(test_identical());
488:   PetscCall(test_disjoint());
489:   PetscCall(test_single_common());
490:   PetscCall(test_issue_1247());

492:   /* Big tests */
493:   /* Test different edge cases with big sets */
494:   PetscCall(test_empty_big());
495:   PetscCall(test_small_big());
496:   PetscCall(test_moderate_big());
497:   PetscCall(test_big_big());
498:   PetscCall(test_big_empty());
499:   PetscCall(test_big_small());
500:   PetscCall(test_big_moderate());
501:   PetscCall(test_big_big_reversed());

503:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
504:   PetscCall(PetscFinalize());
505:   return 0;
506: }

508: /*TEST

510:    test:
511:      suffix: 0

513: TEST*/