1 static char help[] = "Tests `PetscGarbageKeySortedIntersect()`\n\n"; 2 3 #include <petscsys.h> 4 #include <petsc/private/garbagecollector.h> 5 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 */ 21 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}; 29 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 } 37 38 /* Populate a set with Square numbers */ 39 PetscErrorCode Square(PetscInt64 **set, PetscInt n) 40 { 41 PetscInt64 ii; 42 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 } 49 50 /* Populate a set with Cube numbers */ 51 PetscErrorCode Cube(PetscInt64 **set, PetscInt n) 52 { 53 PetscInt64 ii; 54 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 } 61 62 /* Populate a set with numbers to sixth power */ 63 PetscErrorCode Sixth(PetscInt64 **set, PetscInt n) 64 { 65 PetscInt64 ii; 66 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 } 73 74 /* Print out the contents of a set */ 75 PetscErrorCode PrintSet(PetscInt64 *set) 76 { 77 char text[64]; 78 PetscInt ii; 79 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 } 89 90 /* Check set equality */ 91 PetscErrorCode AssertSetsEqual(PetscInt64 *set, PetscInt64 *true_set) 92 { 93 PetscInt ii; 94 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 } 100 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; 107 108 PetscFunctionBeginUser; 109 PetscCall(PetscMalloc1(1, &set_a)); 110 PetscCall(PetscMalloc1(1, &set_b)); 111 112 set_a[0] = 0; 113 114 set_b[0] = 0; 115 116 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 117 PetscCall(PrintSet(set_a)); 118 PetscCall(AssertSetsEqual(set_a, truth)); 119 120 PetscCall(PetscFree(set_a)); 121 PetscCall(PetscFree(set_b)); 122 PetscFunctionReturn(PETSC_SUCCESS); 123 } 124 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; 131 132 PetscFunctionBeginUser; 133 PetscCall(PetscMalloc1(1, &set_a)); 134 PetscCall(PetscMalloc1(2, &set_b)); 135 136 set_a[0] = 0; 137 138 set_b[0] = 1; 139 set_b[1] = 1; 140 141 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 142 PetscCall(PrintSet(set_a)); 143 PetscCall(AssertSetsEqual(set_a, truth)); 144 145 PetscCall(PetscFree(set_a)); 146 PetscCall(PetscFree(set_b)); 147 PetscFunctionReturn(PETSC_SUCCESS); 148 } 149 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; 156 157 PetscFunctionBeginUser; 158 PetscCall(PetscMalloc1(2, &set_a)); 159 PetscCall(PetscMalloc1(1, &set_b)); 160 161 set_a[0] = 1; 162 set_a[1] = 1; 163 164 set_b[0] = 0; 165 166 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 167 PetscCall(PrintSet(set_a)); 168 PetscCall(AssertSetsEqual(set_a, truth)); 169 170 PetscCall(PetscFree(set_a)); 171 PetscCall(PetscFree(set_b)); 172 PetscFunctionReturn(PETSC_SUCCESS); 173 } 174 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; 181 182 PetscFunctionBeginUser; 183 PetscCall(PetscMalloc1(4, &set_a)); 184 PetscCall(PetscMalloc1(4, &set_b)); 185 186 set_a[0] = 3; 187 set_a[1] = 1; 188 set_a[2] = 4; 189 set_a[3] = 9; 190 191 set_b[0] = 3; 192 set_b[1] = 1; 193 set_b[2] = 4; 194 set_b[3] = 9; 195 196 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 197 PetscCall(PrintSet(set_a)); 198 PetscCall(AssertSetsEqual(set_a, truth)); 199 200 PetscCall(PetscFree(set_a)); 201 PetscCall(PetscFree(set_b)); 202 PetscFunctionReturn(PETSC_SUCCESS); 203 } 204 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; 211 212 PetscFunctionBeginUser; 213 PetscCall(PetscMalloc1(4, &set_a)); 214 PetscCall(PetscMalloc1(4, &set_b)); 215 216 set_a[0] = 3; 217 set_a[1] = 1; 218 set_a[2] = 4; 219 set_a[3] = 9; 220 221 set_b[0] = 3; 222 set_b[1] = 2; 223 set_b[2] = 6; 224 set_b[3] = 8; 225 226 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 227 PetscCall(PrintSet(set_a)); 228 PetscCall(AssertSetsEqual(set_a, truth)); 229 230 PetscCall(PetscFree(set_a)); 231 PetscCall(PetscFree(set_b)); 232 PetscFunctionReturn(PETSC_SUCCESS); 233 } 234 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; 241 242 PetscFunctionBeginUser; 243 PetscCall(PetscMalloc1(4, &set_a)); 244 PetscCall(PetscMalloc1(5, &set_b)); 245 246 set_a[0] = 3; 247 set_a[1] = 1; 248 set_a[2] = 4; 249 set_a[3] = 9; 250 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; 256 257 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 258 PetscCall(PrintSet(set_a)); 259 PetscCall(AssertSetsEqual(set_a, truth)); 260 261 PetscCall(PetscFree(set_a)); 262 PetscCall(PetscFree(set_b)); 263 PetscFunctionReturn(PETSC_SUCCESS); 264 } 265 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; 272 273 PetscFunctionBeginUser; 274 PetscCall(PetscMalloc1(3, &set_a)); 275 PetscCall(PetscMalloc1(2, &set_b)); 276 277 set_a[0] = 2; 278 set_a[1] = 2; 279 set_a[2] = 3; 280 281 set_b[0] = 1; 282 set_b[1] = 1; 283 284 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 285 PetscCall(PrintSet(set_a)); 286 PetscCall(AssertSetsEqual(set_a, truth)); 287 288 PetscCall(PetscFree(set_a)); 289 PetscCall(PetscFree(set_b)); 290 PetscFunctionReturn(PETSC_SUCCESS); 291 } 292 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; 299 300 PetscFunctionBeginUser; 301 PetscCall(PetscMalloc1(1, &set_a)); 302 PetscCall(Square(&set_b, 999)); 303 304 set_a[0] = 0; 305 306 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 307 PetscCall(PrintSet(set_a)); 308 PetscCall(AssertSetsEqual(set_a, truth)); 309 310 PetscCall(PetscFree(set_a)); 311 PetscCall(PetscFree(set_b)); 312 PetscFunctionReturn(PETSC_SUCCESS); 313 } 314 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; 321 322 PetscFunctionBeginUser; 323 PetscCall(PetscMalloc1(5, &set_a)); 324 PetscCall(Square(&set_b, 999)); 325 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; 331 332 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 333 PetscCall(PrintSet(set_a)); 334 PetscCall(AssertSetsEqual(set_a, truth)); 335 336 PetscCall(PetscFree(set_a)); 337 PetscCall(PetscFree(set_b)); 338 PetscFunctionReturn(PETSC_SUCCESS); 339 } 340 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; 347 348 PetscFunctionBeginUser; 349 PetscCall(Fibonnaci(&set_a, 49)); 350 PetscCall(Square(&set_b, 999)); 351 352 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 353 PetscCall(PrintSet(set_a)); 354 PetscCall(AssertSetsEqual(set_a, truth)); 355 356 PetscCall(PetscFree(set_a)); 357 PetscCall(PetscFree(set_b)); 358 PetscFunctionReturn(PETSC_SUCCESS); 359 } 360 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; 367 368 PetscFunctionBeginUser; 369 PetscCall(Cube(&set_a, 999)); 370 PetscCall(Square(&set_b, 999)); 371 372 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 373 PetscCall(PrintSet(set_a)); 374 375 PetscCall(Sixth(&truth, 9)); 376 PetscCall(AssertSetsEqual(set_a, truth)); 377 378 PetscCall(PetscFree(set_a)); 379 PetscCall(PetscFree(set_b)); 380 PetscCall(PetscFree(truth)); 381 PetscFunctionReturn(PETSC_SUCCESS); 382 } 383 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; 390 391 PetscFunctionBeginUser; 392 PetscCall(Cube(&set_a, 999)); 393 PetscCall(PetscMalloc1(1, &set_b)); 394 395 set_b[0] = 0; 396 397 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 398 PetscCall(PrintSet(set_a)); 399 PetscCall(AssertSetsEqual(set_a, truth)); 400 401 PetscCall(PetscFree(set_a)); 402 PetscCall(PetscFree(set_b)); 403 PetscFunctionReturn(PETSC_SUCCESS); 404 } 405 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; 412 413 PetscFunctionBeginUser; 414 PetscCall(Cube(&set_a, 999)); 415 PetscCall(PetscMalloc1(5, &set_b)); 416 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; 422 423 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 424 PetscCall(PrintSet(set_a)); 425 PetscCall(AssertSetsEqual(set_a, truth)); 426 427 PetscCall(PetscFree(set_a)); 428 PetscCall(PetscFree(set_b)); 429 PetscFunctionReturn(PETSC_SUCCESS); 430 } 431 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; 438 439 PetscFunctionBeginUser; 440 PetscCall(Cube(&set_a, 999)); 441 PetscCall(Fibonnaci(&set_b, 49)); 442 443 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 444 PetscCall(PrintSet(set_a)); 445 PetscCall(AssertSetsEqual(set_a, truth)); 446 447 PetscCall(PetscFree(set_a)); 448 PetscCall(PetscFree(set_b)); 449 PetscFunctionReturn(PETSC_SUCCESS); 450 } 451 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; 459 460 PetscFunctionBeginUser; 461 PetscCall(Cube(&set_a, 999)); 462 PetscCall(Square(&set_b, 999)); 463 464 PetscGarbageKeySortedIntersect((void *)set_b, (void *)set_a, &length, NULL); 465 PetscCall(PrintSet(set_a)); 466 467 PetscCall(Sixth(&truth, 9)); 468 PetscCall(AssertSetsEqual(set_a, truth)); 469 470 PetscCall(PetscFree(set_a)); 471 PetscCall(PetscFree(set_b)); 472 PetscCall(PetscFree(truth)); 473 PetscFunctionReturn(PETSC_SUCCESS); 474 } 475 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, (char *)0, help)); 481 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()); 491 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()); 502 503 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "ALL PASSED\n")); 504 PetscCall(PetscFinalize()); 505 return 0; 506 } 507 508 /*TEST 509 510 test: 511 suffix: 0 512 513 TEST*/ 514