1 2 /* 3 This file contains routines for sorting integers. Values are sorted in place. 4 */ 5 #include <petscsys.h> /*I "petscsys.h" I*/ 6 7 #define SWAP(a,b,t) {t=a;a=b;b=t;} 8 9 #define MEDIAN3(v,a,b,c) \ 10 (v[a]<v[b] \ 11 ? (v[b]<v[c] \ 12 ? b \ 13 : (v[a]<v[c] ? c : a)) \ 14 : (v[c]<v[b] \ 15 ? b \ 16 : (v[a]<v[c] ? a : c))) 17 18 #define MEDIAN(v,right) MEDIAN3(v,right/4,right/2,right/4*3) 19 20 /* -----------------------------------------------------------------------*/ 21 22 #undef __FUNCT__ 23 #define __FUNCT__ "PetscSortInt_Private" 24 /* 25 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 26 Assumes 0 origin for v, number of elements = right+1 (right is index of 27 right-most member). 28 */ 29 static void PetscSortInt_Private(PetscInt *v,PetscInt right) 30 { 31 PetscInt i,j,pivot,tmp; 32 33 if (right <= 1) { 34 if (right == 1) { 35 if (v[0] > v[1]) SWAP(v[0],v[1],tmp); 36 } 37 return; 38 } 39 i = MEDIAN(v,right); /* Choose a pivot */ 40 SWAP(v[0],v[i],tmp); /* Move it out of the way */ 41 pivot = v[0]; 42 for (i=0,j=right+1;;) { 43 while (++i < j && v[i] <= pivot); /* Scan from the left */ 44 while (v[--j] > pivot); /* Scan from the right */ 45 if (i >= j) break; 46 SWAP(v[i],v[j],tmp); 47 } 48 SWAP(v[0],v[j],tmp); /* Put pivot back in place. */ 49 PetscSortInt_Private(v,j-1); 50 PetscSortInt_Private(v+j+1,right-(j+1)); 51 } 52 53 #undef __FUNCT__ 54 #define __FUNCT__ "PetscSortInt" 55 /*@ 56 PetscSortInt - Sorts an array of integers in place in increasing order. 57 58 Not Collective 59 60 Input Parameters: 61 + n - number of values 62 - i - array of integers 63 64 Level: intermediate 65 66 Concepts: sorting^ints 67 68 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 69 @*/ 70 PetscErrorCode PetscSortInt(PetscInt n,PetscInt i[]) 71 { 72 PetscInt j,k,tmp,ik; 73 74 PetscFunctionBegin; 75 if (n<8) { 76 for (k=0; k<n; k++) { 77 ik = i[k]; 78 for (j=k+1; j<n; j++) { 79 if (ik > i[j]) { 80 SWAP(i[k],i[j],tmp); 81 ik = i[k]; 82 } 83 } 84 } 85 } else { 86 PetscSortInt_Private(i,n-1); 87 } 88 PetscFunctionReturn(0); 89 } 90 91 #undef __FUNCT__ 92 #define __FUNCT__ "PetscSortRemoveDupsInt" 93 /*@ 94 PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries 95 96 Not Collective 97 98 Input Parameters: 99 + n - number of values 100 - ii - array of integers 101 102 Output Parameter: 103 . n - number of non-redundant values 104 105 Level: intermediate 106 107 Concepts: sorting^ints 108 109 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt() 110 @*/ 111 PetscErrorCode PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[]) 112 { 113 PetscErrorCode ierr; 114 PetscInt i,s = 0,N = *n, b = 0; 115 116 PetscFunctionBegin; 117 ierr = PetscSortInt(N,ii);CHKERRQ(ierr); 118 for (i=0; i<N-1; i++) { 119 if (ii[b+s+1] != ii[b]) {ii[b+1] = ii[b+s+1]; b++;} 120 else s++; 121 } 122 *n = N - s; 123 PetscFunctionReturn(0); 124 } 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "PetscFindInt" 128 /*@ 129 PetscFindInt - Finds integer in a sorted array of integers 130 131 Not Collective 132 133 Input Parameters: 134 + key - the integer to locate 135 . n - number of values in the array 136 - ii - array of integers 137 138 Output Parameter: 139 . loc - the location if found, otherwise -(slot+1) where slot is the place the value would go 140 141 Level: intermediate 142 143 Concepts: sorting^ints 144 145 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt() 146 @*/ 147 PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc) 148 { 149 PetscInt lo = 0,hi = n; 150 151 PetscFunctionBegin; 152 PetscValidPointer(loc,4); 153 if (!n) {*loc = -1; PetscFunctionReturn(0);} 154 PetscValidPointer(ii,3); 155 while (hi - lo > 1) { 156 PetscInt mid = lo + (hi - lo)/2; 157 if (key < ii[mid]) hi = mid; 158 else lo = mid; 159 } 160 *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1); 161 PetscFunctionReturn(0); 162 } 163 164 165 /* -----------------------------------------------------------------------*/ 166 #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;} 167 168 #undef __FUNCT__ 169 #define __FUNCT__ "PetscSortIntWithArray_Private" 170 /* 171 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 172 Assumes 0 origin for v, number of elements = right+1 (right is index of 173 right-most member). 174 */ 175 static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right) 176 { 177 PetscErrorCode ierr; 178 PetscInt i,vl,last,tmp; 179 180 PetscFunctionBegin; 181 if (right <= 1) { 182 if (right == 1) { 183 if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp); 184 } 185 PetscFunctionReturn(0); 186 } 187 SWAP2(v[0],v[right/2],V[0],V[right/2],tmp); 188 vl = v[0]; 189 last = 0; 190 for (i=1; i<=right; i++) { 191 if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);} 192 } 193 SWAP2(v[0],v[last],V[0],V[last],tmp); 194 ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr); 195 ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 196 PetscFunctionReturn(0); 197 } 198 199 #undef __FUNCT__ 200 #define __FUNCT__ "PetscSortIntWithArray" 201 /*@ 202 PetscSortIntWithArray - Sorts an array of integers in place in increasing order; 203 changes a second array to match the sorted first array. 204 205 Not Collective 206 207 Input Parameters: 208 + n - number of values 209 . i - array of integers 210 - I - second array of integers 211 212 Level: intermediate 213 214 Concepts: sorting^ints with array 215 216 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt() 217 @*/ 218 PetscErrorCode PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[]) 219 { 220 PetscErrorCode ierr; 221 PetscInt j,k,tmp,ik; 222 223 PetscFunctionBegin; 224 if (n<8) { 225 for (k=0; k<n; k++) { 226 ik = i[k]; 227 for (j=k+1; j<n; j++) { 228 if (ik > i[j]) { 229 SWAP2(i[k],i[j],Ii[k],Ii[j],tmp); 230 ik = i[k]; 231 } 232 } 233 } 234 } else { 235 ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr); 236 } 237 PetscFunctionReturn(0); 238 } 239 240 241 #define SWAP3(a,b,c,d,e,f,t) {t=a;a=b;b=t;t=c;c=d;d=t;t=e;e=f;f=t;} 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "PetscSortIntWithArrayPair_Private" 245 /* 246 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 247 Assumes 0 origin for v, number of elements = right+1 (right is index of 248 right-most member). 249 */ 250 static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right) 251 { 252 PetscErrorCode ierr; 253 PetscInt i,vl,last,tmp; 254 255 PetscFunctionBegin; 256 if (right <= 1) { 257 if (right == 1) { 258 if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp); 259 } 260 PetscFunctionReturn(0); 261 } 262 SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp); 263 vl = L[0]; 264 last = 0; 265 for (i=1; i<=right; i++) { 266 if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);} 267 } 268 SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp); 269 ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr); 270 ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr); 271 PetscFunctionReturn(0); 272 } 273 274 #undef __FUNCT__ 275 #define __FUNCT__ "PetscSortIntWithArrayPair" 276 /*@ 277 PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order; 278 changes a pair of integer arrays to match the sorted first array. 279 280 Not Collective 281 282 Input Parameters: 283 + n - number of values 284 . I - array of integers 285 . J - second array of integers (first array of the pair) 286 - K - third array of integers (second array of the pair) 287 288 Level: intermediate 289 290 Concepts: sorting^ints with array pair 291 292 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray() 293 @*/ 294 PetscErrorCode PetscSortIntWithArrayPair(PetscInt n,PetscInt *L,PetscInt *J, PetscInt *K) 295 { 296 PetscErrorCode ierr; 297 PetscInt j,k,tmp,ik; 298 299 PetscFunctionBegin; 300 if (n<8) { 301 for (k=0; k<n; k++) { 302 ik = L[k]; 303 for (j=k+1; j<n; j++) { 304 if (ik > L[j]) { 305 SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp); 306 ik = L[k]; 307 } 308 } 309 } 310 } else { 311 ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr); 312 } 313 PetscFunctionReturn(0); 314 } 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "PetscSortMPIInt_Private" 318 /* 319 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 320 Assumes 0 origin for v, number of elements = right+1 (right is index of 321 right-most member). 322 */ 323 static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right) 324 { 325 PetscInt i,j; 326 PetscMPIInt pivot,tmp; 327 328 if (right <= 1) { 329 if (right == 1) { 330 if (v[0] > v[1]) SWAP(v[0],v[1],tmp); 331 } 332 return; 333 } 334 i = MEDIAN(v,right); /* Choose a pivot */ 335 SWAP(v[0],v[i],tmp); /* Move it out of the way */ 336 pivot = v[0]; 337 for (i=0,j=right+1;;) { 338 while (++i < j && v[i] <= pivot); /* Scan from the left */ 339 while (v[--j] > pivot); /* Scan from the right */ 340 if (i >= j) break; 341 SWAP(v[i],v[j],tmp); 342 } 343 SWAP(v[0],v[j],tmp); /* Put pivot back in place. */ 344 PetscSortMPIInt_Private(v,j-1); 345 PetscSortMPIInt_Private(v+j+1,right-(j+1)); 346 } 347 348 #undef __FUNCT__ 349 #define __FUNCT__ "PetscSortMPIInt" 350 /*@ 351 PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order. 352 353 Not Collective 354 355 Input Parameters: 356 + n - number of values 357 - i - array of integers 358 359 Level: intermediate 360 361 Concepts: sorting^ints 362 363 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 364 @*/ 365 PetscErrorCode PetscSortMPIInt(PetscInt n,PetscMPIInt i[]) 366 { 367 PetscInt j,k; 368 PetscMPIInt tmp,ik; 369 370 PetscFunctionBegin; 371 if (n<8) { 372 for (k=0; k<n; k++) { 373 ik = i[k]; 374 for (j=k+1; j<n; j++) { 375 if (ik > i[j]) { 376 SWAP(i[k],i[j],tmp); 377 ik = i[k]; 378 } 379 } 380 } 381 } else { 382 PetscSortMPIInt_Private(i,n-1); 383 } 384 PetscFunctionReturn(0); 385 } 386 387 #undef __FUNCT__ 388 #define __FUNCT__ "PetscSortRemoveDupsMPIInt" 389 /*@ 390 PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries 391 392 Not Collective 393 394 Input Parameters: 395 + n - number of values 396 - ii - array of integers 397 398 Output Parameter: 399 . n - number of non-redundant values 400 401 Level: intermediate 402 403 Concepts: sorting^ints 404 405 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt() 406 @*/ 407 PetscErrorCode PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[]) 408 { 409 PetscErrorCode ierr; 410 PetscInt i,s = 0,N = *n, b = 0; 411 412 PetscFunctionBegin; 413 ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr); 414 for (i=0; i<N-1; i++) { 415 if (ii[b+s+1] != ii[b]) {ii[b+1] = ii[b+s+1]; b++;} 416 else s++; 417 } 418 *n = N - s; 419 PetscFunctionReturn(0); 420 } 421 422 #undef __FUNCT__ 423 #define __FUNCT__ "PetscSortMPIIntWithArray_Private" 424 /* 425 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 426 Assumes 0 origin for v, number of elements = right+1 (right is index of 427 right-most member). 428 */ 429 static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right) 430 { 431 PetscErrorCode ierr; 432 PetscMPIInt i,vl,last,tmp; 433 434 PetscFunctionBegin; 435 if (right <= 1) { 436 if (right == 1) { 437 if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp); 438 } 439 PetscFunctionReturn(0); 440 } 441 SWAP2(v[0],v[right/2],V[0],V[right/2],tmp); 442 vl = v[0]; 443 last = 0; 444 for (i=1; i<=right; i++) { 445 if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);} 446 } 447 SWAP2(v[0],v[last],V[0],V[last],tmp); 448 ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr); 449 ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 450 PetscFunctionReturn(0); 451 } 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "PetscSortMPIIntWithArray" 455 /*@ 456 PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order; 457 changes a second array to match the sorted first array. 458 459 Not Collective 460 461 Input Parameters: 462 + n - number of values 463 . i - array of integers 464 - I - second array of integers 465 466 Level: intermediate 467 468 Concepts: sorting^ints with array 469 470 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt() 471 @*/ 472 PetscErrorCode PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[]) 473 { 474 PetscErrorCode ierr; 475 PetscMPIInt j,k,tmp,ik; 476 477 PetscFunctionBegin; 478 if (n<8) { 479 for (k=0; k<n; k++) { 480 ik = i[k]; 481 for (j=k+1; j<n; j++) { 482 if (ik > i[j]) { 483 SWAP2(i[k],i[j],Ii[k],Ii[j],tmp); 484 ik = i[k]; 485 } 486 } 487 } 488 } else { 489 ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr); 490 } 491 PetscFunctionReturn(0); 492 } 493 494 /* -----------------------------------------------------------------------*/ 495 #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;} 496 497 #undef __FUNCT__ 498 #define __FUNCT__ "PetscSortIntWithScalarArray_Private" 499 /* 500 Modified from PetscSortIntWithArray_Private(). 501 */ 502 static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right) 503 { 504 PetscErrorCode ierr; 505 PetscInt i,vl,last,tmp; 506 PetscScalar stmp; 507 508 PetscFunctionBegin; 509 if (right <= 1) { 510 if (right == 1) { 511 if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp); 512 } 513 PetscFunctionReturn(0); 514 } 515 SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp); 516 vl = v[0]; 517 last = 0; 518 for (i=1; i<=right; i++) { 519 if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);} 520 } 521 SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp); 522 ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr); 523 ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 524 PetscFunctionReturn(0); 525 } 526 527 #undef __FUNCT__ 528 #define __FUNCT__ "PetscSortIntWithScalarArray" 529 /*@ 530 PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order; 531 changes a second SCALAR array to match the sorted first INTEGER array. 532 533 Not Collective 534 535 Input Parameters: 536 + n - number of values 537 . i - array of integers 538 - I - second array of scalars 539 540 Level: intermediate 541 542 Concepts: sorting^ints with array 543 544 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 545 @*/ 546 PetscErrorCode PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[]) 547 { 548 PetscErrorCode ierr; 549 PetscInt j,k,tmp,ik; 550 PetscScalar stmp; 551 552 PetscFunctionBegin; 553 if (n<8) { 554 for (k=0; k<n; k++) { 555 ik = i[k]; 556 for (j=k+1; j<n; j++) { 557 if (ik > i[j]) { 558 SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp); 559 ik = i[k]; 560 } 561 } 562 } 563 } else { 564 ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr); 565 } 566 PetscFunctionReturn(0); 567 } 568 569 570 571 #undef __FUNCT__ 572 #define __FUNCT__ "PetscMergeIntArrayPair" 573 /*@ 574 PetscMergeIntArrayPair - Merges two SORTED integer arrays along with an additional array of integers. 575 The additional arrays are the same length as sorted arrays and are merged 576 in the order determined by the merging of the sorted pair. 577 578 Not Collective 579 580 Input Parameters: 581 + an - number of values in the first array 582 . aI - first sorted array of integers 583 . aJ - first additional array of integers 584 . bn - number of values in the second array 585 . bI - second array of integers 586 - bJ - second additional of integers 587 588 Output Parameters: 589 + n - number of values in the merged array (== an + bn) 590 . I - merged sorted array 591 - J - merged additional array 592 593 Level: intermediate 594 595 Concepts: merging^arrays 596 597 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 598 @*/ 599 PetscErrorCode PetscMergeIntArrayPair(PetscInt an,const PetscInt *aI, const PetscInt *aJ, PetscInt bn, const PetscInt *bI, const PetscInt *bJ, PetscInt *n, PetscInt **L, PetscInt **J) 600 { 601 PetscErrorCode ierr; 602 PetscInt n_, *L_ = *L, *J_= *J, ak, bk, k; 603 604 n_ = an + bn; 605 *n = n_; 606 if (!L_) { 607 ierr = PetscMalloc(n_*sizeof(PetscInt), L); CHKERRQ(ierr); 608 L_ = *L; 609 } 610 if (!J_){ 611 ierr = PetscMalloc(n_*sizeof(PetscInt), &J_); CHKERRQ(ierr); 612 J_ = *J; 613 } 614 k = ak = bk = 0; 615 while(ak < an && bk < bn) { 616 if (aI[ak] <= bI[bk]) { 617 L_[k] = aI[ak]; 618 J_[k] = aJ[ak]; 619 ++ak; 620 ++k; 621 } 622 else { 623 L_[k] = bI[bk]; 624 J_[k] = bJ[bk]; 625 ++bk; 626 ++k; 627 } 628 } 629 if (ak < an) { 630 ierr = PetscMemcpy(L_+k,aI+ak,(an-ak)*sizeof(PetscInt)); CHKERRQ(ierr); 631 ierr = PetscMemcpy(J_+k,aJ+ak,(an-ak)*sizeof(PetscInt)); CHKERRQ(ierr); 632 k += (an-ak); 633 } 634 if (bk < bn) { 635 ierr = PetscMemcpy(L_+k,bI+bk,(bn-bk)*sizeof(PetscInt)); CHKERRQ(ierr); 636 ierr = PetscMemcpy(J_+k,bJ+bk,(bn-bk)*sizeof(PetscInt)); CHKERRQ(ierr); 637 k += (bn-bk); 638 } 639 PetscFunctionReturn(0); 640 } 641 642 643 #undef __FUNCT__ 644 #define __FUNCT__ "PetscProcessTree" 645 /*@ 646 PetscProcessTree - Prepares tree data to be displayed graphically 647 648 Not Collective 649 650 Input Parameters: 651 + n - number of values 652 . mask - indicates those entries in the tree, location 0 is always masked 653 - parentid - indicates the parent of each entry 654 655 Output Parameters: 656 + Nlevels - the number of levels 657 . Level - for each node tells its level 658 . Levelcnts - the number of nodes on each level 659 . Idbylevel - a list of ids on each of the levels, first level followed by second etc 660 - Column - for each id tells its column index 661 662 Level: intermediate 663 664 665 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 666 @*/ 667 PetscErrorCode PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column) 668 { 669 PetscInt i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column; 670 PetscErrorCode ierr; 671 PetscBool done = PETSC_FALSE; 672 673 PetscFunctionBegin; 674 if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set"); 675 for (i=0; i<n; i++) { 676 if (mask[i]) continue; 677 if (parentid[i] == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent"); 678 if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked"); 679 } 680 681 682 for (i=0; i<n; i++) { 683 if (!mask[i]) nmask++; 684 } 685 686 /* determine the level in the tree of each node */ 687 ierr = PetscMalloc(n*sizeof(PetscInt),&level);CHKERRQ(ierr); 688 ierr = PetscMemzero(level,n*sizeof(PetscInt));CHKERRQ(ierr); 689 level[0] = 1; 690 while (!done) { 691 done = PETSC_TRUE; 692 for (i=0; i<n; i++) { 693 if (mask[i]) continue; 694 if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1; 695 else if (!level[i]) done = PETSC_FALSE; 696 } 697 } 698 for (i=0; i<n; i++) { 699 level[i]--; 700 nlevels = PetscMax(nlevels,level[i]); 701 } 702 703 /* count the number of nodes on each level and its max */ 704 ierr = PetscMalloc(nlevels*sizeof(PetscInt),&levelcnt);CHKERRQ(ierr); 705 ierr = PetscMemzero(levelcnt,nlevels*sizeof(PetscInt));CHKERRQ(ierr); 706 for (i=0; i<n; i++) { 707 if (mask[i]) continue; 708 levelcnt[level[i]-1]++; 709 } 710 for (i=0; i<nlevels;i++) { 711 levelmax = PetscMax(levelmax,levelcnt[i]); 712 } 713 714 /* for each level sort the ids by the parent id */ 715 ierr = PetscMalloc2(levelmax,PetscInt,&workid,levelmax,PetscInt,&workparentid);CHKERRQ(ierr); 716 ierr = PetscMalloc(nmask*sizeof(PetscInt),&idbylevel);CHKERRQ(ierr); 717 for (j=1; j<=nlevels;j++) { 718 cnt = 0; 719 for (i=0; i<n; i++) { 720 if (mask[i]) continue; 721 if (level[i] != j) continue; 722 workid[cnt] = i; 723 workparentid[cnt++] = parentid[i]; 724 } 725 /* PetscIntView(cnt,workparentid,0); 726 PetscIntView(cnt,workid,0); 727 ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr); 728 PetscIntView(cnt,workparentid,0); 729 PetscIntView(cnt,workid,0);*/ 730 ierr = PetscMemcpy(idbylevel+tcnt,workid,cnt*sizeof(PetscInt));CHKERRQ(ierr); 731 tcnt += cnt; 732 } 733 if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes"); 734 ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr); 735 736 /* for each node list its column */ 737 ierr = PetscMalloc(n*sizeof(PetscInt),&column);CHKERRQ(ierr); 738 cnt = 0; 739 for (j=0; j<nlevels; j++) { 740 for (i=0; i<levelcnt[j]; i++) { 741 column[idbylevel[cnt++]] = i; 742 } 743 } 744 745 *Nlevels = nlevels; 746 *Level = level; 747 *Levelcnt = levelcnt; 748 *Idbylevel = idbylevel; 749 *Column = column; 750 PetscFunctionReturn(0); 751 } 752