Actual source code: ex62.c

  1: static char help[] = "Tests PetscGarbageKeySortedIntersect()\n\n";

  3: #include <petsc/private/garbagecollector.h>

  5: /* This program tests PetscGarbageKeySortedIntersect(), which is the
  6:    public (MPI) interface to
  7:    PetscErrorCode GarbageKeySortedIntersect_Private().
  8:    Sets are sent packed in arrays, with the first entry as the number of
  9:    set elements and the sets the remaining elements. This is because the
 10:    MPI reduction operation must have the call signature:
 11:    void PetscGarbageKeySortedIntersect(void *inset, void *inoutset, PetscMPIInt *length, MPI_Datatype *dtype)
 12:    This is a thin wrapper for the private routine:
 13:    PetscErrorCode GarbageKeySortedIntersect_Private(PetscInt64 seta[], PetscInt *lena, PetscInt64 setb[], PetscInt lenb)
 14:    Where
 15:    seta = (PetscInt64 *)inoutset;
 16:    setb = (PetscInt64 *)inset;
 17:    And the arguments are passed as:
 18:    &seta[1], (PetscInt *)&seta[0], &setb[1], (PetscInt)setb[0]
 19: */

 21: /* Populate a set with upto the first 49 unique Fibonnaci numbers */
 22: PetscErrorCode Fibonnaci(PetscInt64 **set, PetscInt n)
 23: {
 24:   PetscInt   ii;
 25:   PetscInt64 fib[] = {1,        2,        3,        5,        8,         13,        21,        34,        55,        89,         144,        233,        377,        610,        987,        1597,    2584,
 26:                       4181,     6765,     10946,    17711,    28657,     46368,     75025,     121393,    196418,    317811,     514229,     832040,     1346269,    2178309,    3524578,    5702887, 9227465,
 27:                       14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025};

 29:   PetscFunctionBeginUser;
 30:   PetscAssert(n < 50, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "n must be less than 50");
 31:   PetscCall(PetscMalloc1(n + 1, set));
 32:   (*set)[0] = n;
 33:   for (ii = 0; ii < n; ii++) (*set)[ii + 1] = fib[ii];
 34:   PetscFunctionReturn(PETSC_SUCCESS);
 35: }

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

 42:   PetscFunctionBeginUser;
 43:   PetscCall(PetscMalloc1(n + 1, set));
 44:   (*set)[0] = n;
 45:   for (ii = 1; ii < n + 1; ii++) (*set)[ii] = ii * ii;
 46:   PetscFunctionReturn(PETSC_SUCCESS);
 47: }

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

 54:   PetscFunctionBeginUser;
 55:   PetscCall(PetscMalloc1(n + 1, set));
 56:   (*set)[0] = n;
 57:   for (ii = 1; ii < n + 1; ii++) (*set)[ii] = ii * ii * ii;
 58:   PetscFunctionReturn(PETSC_SUCCESS);
 59: }

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

 66:   PetscFunctionBeginUser;
 67:   PetscCall(PetscMalloc1(n + 1, set));
 68:   (*set)[0] = n;
 69:   for (ii = 1; ii < n + 1; ii++) (*set)[ii] = ii * ii * ii * ii * ii * ii;
 70:   PetscFunctionReturn(PETSC_SUCCESS);
 71: }

 73: /* Print out the contents of a set */
 74: PetscErrorCode PrintSet(PetscInt64 *set)
 75: {
 76:   char text[64];

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

 88: /* Check set equality */
 89: PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set)
 90: {
 91:   PetscFunctionBeginUser;
 92:   PetscAssert(set[0] == true_set[0], PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Sets of different sizes");
 93:   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");
 94:   PetscFunctionReturn(PETSC_SUCCESS);
 95: }

 97: /* Tests functionality when two enpty sets are passed */
 98: PetscErrorCode test_empty_empty(void)
 99: {
100:   PetscInt64 *set_a, *set_b;
101:   PetscInt64  truth[] = {0};
102:   PetscMPIInt length  = 1;

104:   PetscFunctionBeginUser;
105:   PetscCall(PetscMalloc1(1, &set_a));
106:   PetscCall(PetscMalloc1(1, &set_b));

108:   set_a[0] = 0;

110:   set_b[0] = 0;

112:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
113:   PetscCall(PrintSet(set_a));
114:   PetscCall(AssertSetsEqual(set_a, truth));

116:   PetscCall(PetscFree(set_a));
117:   PetscCall(PetscFree(set_b));
118:   PetscFunctionReturn(PETSC_SUCCESS);
119: }

121: /* Tests functionality when seta is empty */
122: PetscErrorCode test_a_empty(void)
123: {
124:   PetscInt64 *set_a, *set_b;
125:   PetscInt64  truth[] = {0};
126:   PetscMPIInt length  = 1;

128:   PetscFunctionBeginUser;
129:   PetscCall(PetscMalloc1(1, &set_a));
130:   PetscCall(PetscMalloc1(2, &set_b));

132:   set_a[0] = 0;

134:   set_b[0] = 1;
135:   set_b[1] = 1;

137:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
138:   PetscCall(PrintSet(set_a));
139:   PetscCall(AssertSetsEqual(set_a, truth));

141:   PetscCall(PetscFree(set_a));
142:   PetscCall(PetscFree(set_b));
143:   PetscFunctionReturn(PETSC_SUCCESS);
144: }

146: /* Tests functionality when setb is empty */
147: PetscErrorCode test_b_empty(void)
148: {
149:   PetscInt64 *set_a, *set_b;
150:   PetscInt64  truth[] = {0};
151:   PetscMPIInt length  = 1;

153:   PetscFunctionBeginUser;
154:   PetscCall(PetscMalloc1(2, &set_a));
155:   PetscCall(PetscMalloc1(1, &set_b));

157:   set_a[0] = 1;
158:   set_a[1] = 1;

160:   set_b[0] = 0;

162:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
163:   PetscCall(PrintSet(set_a));
164:   PetscCall(AssertSetsEqual(set_a, truth));

166:   PetscCall(PetscFree(set_a));
167:   PetscCall(PetscFree(set_b));
168:   PetscFunctionReturn(PETSC_SUCCESS);
169: }

171: /* Tests functionality when both sets are identical */
172: PetscErrorCode test_identical(void)
173: {
174:   PetscInt64 *set_a, *set_b;
175:   PetscInt64  truth[] = {3, 1, 4, 9};
176:   PetscMPIInt length  = 4;

178:   PetscFunctionBeginUser;
179:   PetscCall(PetscMalloc1(4, &set_a));
180:   PetscCall(PetscMalloc1(4, &set_b));

182:   set_a[0] = 3;
183:   set_a[1] = 1;
184:   set_a[2] = 4;
185:   set_a[3] = 9;

187:   set_b[0] = 3;
188:   set_b[1] = 1;
189:   set_b[2] = 4;
190:   set_b[3] = 9;

192:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
193:   PetscCall(PrintSet(set_a));
194:   PetscCall(AssertSetsEqual(set_a, truth));

196:   PetscCall(PetscFree(set_a));
197:   PetscCall(PetscFree(set_b));
198:   PetscFunctionReturn(PETSC_SUCCESS);
199: }

201: /* Tests functionality when sets have no elements in common */
202: PetscErrorCode test_disjoint(void)
203: {
204:   PetscInt64 *set_a, *set_b;
205:   PetscInt64  truth[] = {0};
206:   PetscMPIInt length  = 1;

208:   PetscFunctionBeginUser;
209:   PetscCall(PetscMalloc1(4, &set_a));
210:   PetscCall(PetscMalloc1(4, &set_b));

212:   set_a[0] = 3;
213:   set_a[1] = 1;
214:   set_a[2] = 4;
215:   set_a[3] = 9;

217:   set_b[0] = 3;
218:   set_b[1] = 2;
219:   set_b[2] = 6;
220:   set_b[3] = 8;

222:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
223:   PetscCall(PrintSet(set_a));
224:   PetscCall(AssertSetsEqual(set_a, truth));

226:   PetscCall(PetscFree(set_a));
227:   PetscCall(PetscFree(set_b));
228:   PetscFunctionReturn(PETSC_SUCCESS);
229: }

231: /* Tests functionality when sets only have one element in common */
232: PetscErrorCode test_single_common(void)
233: {
234:   PetscInt64 *set_a, *set_b;
235:   PetscInt64  truth[] = {1, 4};
236:   PetscMPIInt length  = 1;

238:   PetscFunctionBeginUser;
239:   PetscCall(PetscMalloc1(4, &set_a));
240:   PetscCall(PetscMalloc1(5, &set_b));

242:   set_a[0] = 3;
243:   set_a[1] = 1;
244:   set_a[2] = 4;
245:   set_a[3] = 9;

247:   set_b[0] = 3;
248:   set_b[1] = 2;
249:   set_b[2] = 4;
250:   set_b[3] = 6;
251:   set_b[4] = 8;

253:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
254:   PetscCall(PrintSet(set_a));
255:   PetscCall(AssertSetsEqual(set_a, truth));

257:   PetscCall(PetscFree(set_a));
258:   PetscCall(PetscFree(set_b));
259:   PetscFunctionReturn(PETSC_SUCCESS);
260: }

262: /* Specific test case flagged by PETSc issue #1247 */
263: PetscErrorCode test_issue_1247(void)
264: {
265:   PetscInt64 *set_a, *set_b;
266:   PetscInt64  truth[] = {0};
267:   PetscMPIInt length  = 1;

269:   PetscFunctionBeginUser;
270:   PetscCall(PetscMalloc1(3, &set_a));
271:   PetscCall(PetscMalloc1(2, &set_b));

273:   set_a[0] = 2;
274:   set_a[1] = 2;
275:   set_a[2] = 3;

277:   set_b[0] = 1;
278:   set_b[1] = 1;

280:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
281:   PetscCall(PrintSet(set_a));
282:   PetscCall(AssertSetsEqual(set_a, truth));

284:   PetscCall(PetscFree(set_a));
285:   PetscCall(PetscFree(set_b));
286:   PetscFunctionReturn(PETSC_SUCCESS);
287: }

289: /* Tests functionality when seta is empty and setb is large */
290: PetscErrorCode test_empty_big(void)
291: {
292:   PetscInt64 *set_a, *set_b;
293:   PetscInt64  truth[] = {0};
294:   PetscMPIInt length  = 1;

296:   PetscFunctionBeginUser;
297:   PetscCall(PetscMalloc1(1, &set_a));
298:   PetscCall(Square(&set_b, 999));

300:   set_a[0] = 0;

302:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
303:   PetscCall(PrintSet(set_a));
304:   PetscCall(AssertSetsEqual(set_a, truth));

306:   PetscCall(PetscFree(set_a));
307:   PetscCall(PetscFree(set_b));
308:   PetscFunctionReturn(PETSC_SUCCESS);
309: }

311: /* Tests functionality when seta is small and setb is large */
312: PetscErrorCode test_small_big(void)
313: {
314:   PetscInt64 *set_a, *set_b;
315:   PetscInt64  truth[] = {3, 1, 4, 9};
316:   PetscMPIInt length  = 1;

318:   PetscFunctionBeginUser;
319:   PetscCall(PetscMalloc1(5, &set_a));
320:   PetscCall(Square(&set_b, 999));

322:   set_a[0] = 4;
323:   set_a[1] = 1;
324:   set_a[2] = 4;
325:   set_a[3] = 8;
326:   set_a[4] = 9;

328:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
329:   PetscCall(PrintSet(set_a));
330:   PetscCall(AssertSetsEqual(set_a, truth));

332:   PetscCall(PetscFree(set_a));
333:   PetscCall(PetscFree(set_b));
334:   PetscFunctionReturn(PETSC_SUCCESS);
335: }

337: /* Tests functionality when seta is medium sized and setb is large */
338: PetscErrorCode test_moderate_big(void)
339: {
340:   PetscInt64 *set_a, *set_b;
341:   PetscInt64  truth[] = {2, 1, 144};
342:   PetscMPIInt length  = 1;

344:   PetscFunctionBeginUser;
345:   PetscCall(Fibonnaci(&set_a, 49));
346:   PetscCall(Square(&set_b, 999));

348:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
349:   PetscCall(PrintSet(set_a));
350:   PetscCall(AssertSetsEqual(set_a, truth));

352:   PetscCall(PetscFree(set_a));
353:   PetscCall(PetscFree(set_b));
354:   PetscFunctionReturn(PETSC_SUCCESS);
355: }

357: /* Tests functionality when seta and setb are large */
358: PetscErrorCode test_big_big(void)
359: {
360:   PetscInt64 *set_a, *set_b;
361:   PetscInt64 *truth;
362:   PetscMPIInt length = 1;

364:   PetscFunctionBeginUser;
365:   PetscCall(Cube(&set_a, 999));
366:   PetscCall(Square(&set_b, 999));

368:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
369:   PetscCall(PrintSet(set_a));

371:   PetscCall(Sixth(&truth, 9));
372:   PetscCall(AssertSetsEqual(set_a, truth));

374:   PetscCall(PetscFree(set_a));
375:   PetscCall(PetscFree(set_b));
376:   PetscCall(PetscFree(truth));
377:   PetscFunctionReturn(PETSC_SUCCESS);
378: }

380: /* Tests functionality when setb is empty and setb is large */
381: PetscErrorCode test_big_empty(void)
382: {
383:   PetscInt64 *set_a, *set_b;
384:   PetscInt64  truth[] = {0};
385:   PetscMPIInt length  = 1;

387:   PetscFunctionBeginUser;
388:   PetscCall(Cube(&set_a, 999));
389:   PetscCall(PetscMalloc1(1, &set_b));

391:   set_b[0] = 0;

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

397:   PetscCall(PetscFree(set_a));
398:   PetscCall(PetscFree(set_b));
399:   PetscFunctionReturn(PETSC_SUCCESS);
400: }

402: /* Tests functionality when setb is small and setb is large */
403: PetscErrorCode test_big_small(void)
404: {
405:   PetscInt64 *set_a, *set_b;
406:   PetscInt64  truth[] = {2, 1, 8};
407:   PetscMPIInt length  = 1;

409:   PetscFunctionBeginUser;
410:   PetscCall(Cube(&set_a, 999));
411:   PetscCall(PetscMalloc1(5, &set_b));

413:   set_b[0] = 4;
414:   set_b[1] = 1;
415:   set_b[2] = 4;
416:   set_b[3] = 8;
417:   set_b[4] = 9;

419:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
420:   PetscCall(PrintSet(set_a));
421:   PetscCall(AssertSetsEqual(set_a, truth));

423:   PetscCall(PetscFree(set_a));
424:   PetscCall(PetscFree(set_b));
425:   PetscFunctionReturn(PETSC_SUCCESS);
426: }

428: /* Tests functionality when setb is medium sized and setb is large */
429: PetscErrorCode test_big_moderate(void)
430: {
431:   PetscInt64 *set_a, *set_b;
432:   PetscInt64  truth[] = {2, 1, 8};
433:   PetscMPIInt length  = 1;

435:   PetscFunctionBeginUser;
436:   PetscCall(Cube(&set_a, 999));
437:   PetscCall(Fibonnaci(&set_b, 49));

439:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
440:   PetscCall(PrintSet(set_a));
441:   PetscCall(AssertSetsEqual(set_a, truth));

443:   PetscCall(PetscFree(set_a));
444:   PetscCall(PetscFree(set_b));
445:   PetscFunctionReturn(PETSC_SUCCESS);
446: }

448: /* Tests functionality when seta and setb are large, in the opposite
449:  order to test_big_big() */
450: PetscErrorCode test_big_big_reversed(void)
451: {
452:   PetscInt64 *set_a, *set_b;
453:   PetscInt64 *truth;
454:   PetscMPIInt length = 1;

456:   PetscFunctionBeginUser;
457:   PetscCall(Cube(&set_a, 999));
458:   PetscCall(Square(&set_b, 999));

460:   PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL);
461:   PetscCall(PrintSet(set_a));

463:   PetscCall(Sixth(&truth, 9));
464:   PetscCall(AssertSetsEqual(set_a, truth));

466:   PetscCall(PetscFree(set_a));
467:   PetscCall(PetscFree(set_b));
468:   PetscCall(PetscFree(truth));
469:   PetscFunctionReturn(PETSC_SUCCESS);
470: }

472: /* Main executes the individual tests in a predefined order */
473: int main(int argc, char **argv)
474: {
475:   PetscFunctionBeginUser;
476:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));

478:   /* Small tests */
479:   /* Test different edge cases with small sets */
480:   PetscCall(test_empty_empty());
481:   PetscCall(test_a_empty());
482:   PetscCall(test_b_empty());
483:   PetscCall(test_identical());
484:   PetscCall(test_disjoint());
485:   PetscCall(test_single_common());
486:   PetscCall(test_issue_1247());

488:   /* Big tests */
489:   /* Test different edge cases with big sets */
490:   PetscCall(test_empty_big());
491:   PetscCall(test_small_big());
492:   PetscCall(test_moderate_big());
493:   PetscCall(test_big_big());
494:   PetscCall(test_big_empty());
495:   PetscCall(test_big_small());
496:   PetscCall(test_big_moderate());
497:   PetscCall(test_big_big_reversed());

499:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n"));
500:   PetscCall(PetscFinalize());
501:   return 0;
502: }

504: /*TEST

506:    test:
507:      suffix: 0

509: TEST*/