1 2 /* 3 This file contains routines for sorting integers. Values are sorted in place. 4 */ 5 #include <petsc/private/petscimpl.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 /* 23 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 24 Assumes 0 origin for v, number of elements = right+1 (right is index of 25 right-most member). 26 */ 27 static void PetscSortInt_Private(PetscInt *v,PetscInt right) 28 { 29 PetscInt i,j,pivot,tmp; 30 31 if (right <= 1) { 32 if (right == 1) { 33 if (v[0] > v[1]) SWAP(v[0],v[1],tmp); 34 } 35 return; 36 } 37 i = MEDIAN(v,right); /* Choose a pivot */ 38 SWAP(v[0],v[i],tmp); /* Move it out of the way */ 39 pivot = v[0]; 40 for (i=0,j=right+1;; ) { 41 while (++i < j && v[i] <= pivot) ; /* Scan from the left */ 42 while (v[--j] > pivot) ; /* Scan from the right */ 43 if (i >= j) break; 44 SWAP(v[i],v[j],tmp); 45 } 46 SWAP(v[0],v[j],tmp); /* Put pivot back in place. */ 47 PetscSortInt_Private(v,j-1); 48 PetscSortInt_Private(v+j+1,right-(j+1)); 49 } 50 51 /*@ 52 PetscSortInt - Sorts an array of integers in place in increasing order. 53 54 Not Collective 55 56 Input Parameters: 57 + n - number of values 58 - i - array of integers 59 60 Level: intermediate 61 62 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 63 @*/ 64 PetscErrorCode PetscSortInt(PetscInt n,PetscInt i[]) 65 { 66 PetscInt j,k,tmp,ik; 67 68 PetscFunctionBegin; 69 if (n<8) { 70 for (k=0; k<n; k++) { 71 ik = i[k]; 72 for (j=k+1; j<n; j++) { 73 if (ik > i[j]) { 74 SWAP(i[k],i[j],tmp); 75 ik = i[k]; 76 } 77 } 78 } 79 } else PetscSortInt_Private(i,n-1); 80 PetscFunctionReturn(0); 81 } 82 83 /*@ 84 PetscSortedRemoveDupsInt - Removes all duplicate entries of a sorted input array 85 86 Not Collective 87 88 Input Parameters: 89 + n - number of values 90 - ii - sorted array of integers 91 92 Output Parameter: 93 . n - number of non-redundant values 94 95 Level: intermediate 96 97 .seealso: PetscSortInt() 98 @*/ 99 PetscErrorCode PetscSortedRemoveDupsInt(PetscInt *n,PetscInt ii[]) 100 { 101 PetscInt i,s = 0,N = *n, b = 0; 102 103 PetscFunctionBegin; 104 for (i=0; i<N-1; i++) { 105 if (PetscUnlikely(ii[b+s+1] < ii[b])) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Input array is not sorted"); 106 if (ii[b+s+1] != ii[b]) { 107 ii[b+1] = ii[b+s+1]; b++; 108 } else s++; 109 } 110 *n = N - s; 111 PetscFunctionReturn(0); 112 } 113 114 /*@ 115 PetscSortRemoveDupsInt - Sorts an array of integers in place in increasing order removes all duplicate entries 116 117 Not Collective 118 119 Input Parameters: 120 + n - number of values 121 - ii - array of integers 122 123 Output Parameter: 124 . n - number of non-redundant values 125 126 Level: intermediate 127 128 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt(), PetscSortedRemoveDupsInt() 129 @*/ 130 PetscErrorCode PetscSortRemoveDupsInt(PetscInt *n,PetscInt ii[]) 131 { 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 ierr = PetscSortInt(*n,ii);CHKERRQ(ierr); 136 ierr = PetscSortedRemoveDupsInt(n,ii);CHKERRQ(ierr); 137 PetscFunctionReturn(0); 138 } 139 140 /*@ 141 PetscFindInt - Finds integer in a sorted array of integers 142 143 Not Collective 144 145 Input Parameters: 146 + key - the integer to locate 147 . n - number of values in the array 148 - ii - array of integers 149 150 Output Parameter: 151 . loc - the location if found, otherwise -(slot+1) where slot is the place the value would go 152 153 Level: intermediate 154 155 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt() 156 @*/ 157 PetscErrorCode PetscFindInt(PetscInt key, PetscInt n, const PetscInt ii[], PetscInt *loc) 158 { 159 PetscInt lo = 0,hi = n; 160 161 PetscFunctionBegin; 162 PetscValidPointer(loc,4); 163 if (!n) {*loc = -1; PetscFunctionReturn(0);} 164 PetscValidPointer(ii,3); 165 while (hi - lo > 1) { 166 PetscInt mid = lo + (hi - lo)/2; 167 if (key < ii[mid]) hi = mid; 168 else lo = mid; 169 } 170 *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1); 171 PetscFunctionReturn(0); 172 } 173 174 /*@ 175 PetscFindMPIInt - Finds MPI integer in a sorted array of integers 176 177 Not Collective 178 179 Input Parameters: 180 + key - the integer to locate 181 . n - number of values in the array 182 - ii - array of integers 183 184 Output Parameter: 185 . loc - the location if found, otherwise -(slot+1) where slot is the place the value would go 186 187 Level: intermediate 188 189 .seealso: PetscSortInt(), PetscSortIntWithArray(), PetscSortRemoveDupsInt() 190 @*/ 191 PetscErrorCode PetscFindMPIInt(PetscMPIInt key, PetscInt n, const PetscMPIInt ii[], PetscInt *loc) 192 { 193 PetscInt lo = 0,hi = n; 194 195 PetscFunctionBegin; 196 PetscValidPointer(loc,4); 197 if (!n) {*loc = -1; PetscFunctionReturn(0);} 198 PetscValidPointer(ii,3); 199 while (hi - lo > 1) { 200 PetscInt mid = lo + (hi - lo)/2; 201 if (key < ii[mid]) hi = mid; 202 else lo = mid; 203 } 204 *loc = key == ii[lo] ? lo : -(lo + (key > ii[lo]) + 1); 205 PetscFunctionReturn(0); 206 } 207 208 /* -----------------------------------------------------------------------*/ 209 #define SWAP2(a,b,c,d,t) {t=a;a=b;b=t;t=c;c=d;d=t;} 210 211 /* 212 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 213 Assumes 0 origin for v, number of elements = right+1 (right is index of 214 right-most member). 215 */ 216 static PetscErrorCode PetscSortIntWithArray_Private(PetscInt *v,PetscInt *V,PetscInt right) 217 { 218 PetscErrorCode ierr; 219 PetscInt i,vl,last,tmp; 220 221 PetscFunctionBegin; 222 if (right <= 1) { 223 if (right == 1) { 224 if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp); 225 } 226 PetscFunctionReturn(0); 227 } 228 SWAP2(v[0],v[right/2],V[0],V[right/2],tmp); 229 vl = v[0]; 230 last = 0; 231 for (i=1; i<=right; i++) { 232 if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);} 233 } 234 SWAP2(v[0],v[last],V[0],V[last],tmp); 235 ierr = PetscSortIntWithArray_Private(v,V,last-1);CHKERRQ(ierr); 236 ierr = PetscSortIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 237 PetscFunctionReturn(0); 238 } 239 240 /*@ 241 PetscSortIntWithArray - Sorts an array of integers in place in increasing order; 242 changes a second array to match the sorted first array. 243 244 Not Collective 245 246 Input Parameters: 247 + n - number of values 248 . i - array of integers 249 - I - second array of integers 250 251 Level: intermediate 252 253 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt() 254 @*/ 255 PetscErrorCode PetscSortIntWithArray(PetscInt n,PetscInt i[],PetscInt Ii[]) 256 { 257 PetscErrorCode ierr; 258 PetscInt j,k,tmp,ik; 259 260 PetscFunctionBegin; 261 if (n<8) { 262 for (k=0; k<n; k++) { 263 ik = i[k]; 264 for (j=k+1; j<n; j++) { 265 if (ik > i[j]) { 266 SWAP2(i[k],i[j],Ii[k],Ii[j],tmp); 267 ik = i[k]; 268 } 269 } 270 } 271 } else { 272 ierr = PetscSortIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr); 273 } 274 PetscFunctionReturn(0); 275 } 276 277 278 #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;} 279 280 /* 281 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 282 Assumes 0 origin for v, number of elements = right+1 (right is index of 283 right-most member). 284 */ 285 static PetscErrorCode PetscSortIntWithArrayPair_Private(PetscInt *L,PetscInt *J, PetscInt *K, PetscInt right) 286 { 287 PetscErrorCode ierr; 288 PetscInt i,vl,last,tmp; 289 290 PetscFunctionBegin; 291 if (right <= 1) { 292 if (right == 1) { 293 if (L[0] > L[1]) SWAP3(L[0],L[1],J[0],J[1],K[0],K[1],tmp); 294 } 295 PetscFunctionReturn(0); 296 } 297 SWAP3(L[0],L[right/2],J[0],J[right/2],K[0],K[right/2],tmp); 298 vl = L[0]; 299 last = 0; 300 for (i=1; i<=right; i++) { 301 if (L[i] < vl) {last++; SWAP3(L[last],L[i],J[last],J[i],K[last],K[i],tmp);} 302 } 303 SWAP3(L[0],L[last],J[0],J[last],K[0],K[last],tmp); 304 ierr = PetscSortIntWithArrayPair_Private(L,J,K,last-1);CHKERRQ(ierr); 305 ierr = PetscSortIntWithArrayPair_Private(L+last+1,J+last+1,K+last+1,right-(last+1));CHKERRQ(ierr); 306 PetscFunctionReturn(0); 307 } 308 309 /*@ 310 PetscSortIntWithArrayPair - Sorts an array of integers in place in increasing order; 311 changes a pair of integer arrays to match the sorted first array. 312 313 Not Collective 314 315 Input Parameters: 316 + n - number of values 317 . I - array of integers 318 . J - second array of integers (first array of the pair) 319 - K - third array of integers (second array of the pair) 320 321 Level: intermediate 322 323 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortIntWithArray() 324 @*/ 325 PetscErrorCode PetscSortIntWithArrayPair(PetscInt n,PetscInt L[],PetscInt J[], PetscInt K[]) 326 { 327 PetscErrorCode ierr; 328 PetscInt j,k,tmp,ik; 329 330 PetscFunctionBegin; 331 if (n<8) { 332 for (k=0; k<n; k++) { 333 ik = L[k]; 334 for (j=k+1; j<n; j++) { 335 if (ik > L[j]) { 336 SWAP3(L[k],L[j],J[k],J[j],K[k],K[j],tmp); 337 ik = L[k]; 338 } 339 } 340 } 341 } else { 342 ierr = PetscSortIntWithArrayPair_Private(L,J,K,n-1);CHKERRQ(ierr); 343 } 344 PetscFunctionReturn(0); 345 } 346 347 /* 348 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 349 Assumes 0 origin for v, number of elements = right+1 (right is index of 350 right-most member). 351 */ 352 static void PetscSortMPIInt_Private(PetscMPIInt *v,PetscInt right) 353 { 354 PetscInt i,j; 355 PetscMPIInt pivot,tmp; 356 357 if (right <= 1) { 358 if (right == 1) { 359 if (v[0] > v[1]) SWAP(v[0],v[1],tmp); 360 } 361 return; 362 } 363 i = MEDIAN(v,right); /* Choose a pivot */ 364 SWAP(v[0],v[i],tmp); /* Move it out of the way */ 365 pivot = v[0]; 366 for (i=0,j=right+1;; ) { 367 while (++i < j && v[i] <= pivot) ; /* Scan from the left */ 368 while (v[--j] > pivot) ; /* Scan from the right */ 369 if (i >= j) break; 370 SWAP(v[i],v[j],tmp); 371 } 372 SWAP(v[0],v[j],tmp); /* Put pivot back in place. */ 373 PetscSortMPIInt_Private(v,j-1); 374 PetscSortMPIInt_Private(v+j+1,right-(j+1)); 375 } 376 377 /*@ 378 PetscSortMPIInt - Sorts an array of MPI integers in place in increasing order. 379 380 Not Collective 381 382 Input Parameters: 383 + n - number of values 384 - i - array of integers 385 386 Level: intermediate 387 388 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 389 @*/ 390 PetscErrorCode PetscSortMPIInt(PetscInt n,PetscMPIInt i[]) 391 { 392 PetscInt j,k; 393 PetscMPIInt tmp,ik; 394 395 PetscFunctionBegin; 396 if (n<8) { 397 for (k=0; k<n; k++) { 398 ik = i[k]; 399 for (j=k+1; j<n; j++) { 400 if (ik > i[j]) { 401 SWAP(i[k],i[j],tmp); 402 ik = i[k]; 403 } 404 } 405 } 406 } else PetscSortMPIInt_Private(i,n-1); 407 PetscFunctionReturn(0); 408 } 409 410 /*@ 411 PetscSortRemoveDupsMPIInt - Sorts an array of MPI integers in place in increasing order removes all duplicate entries 412 413 Not Collective 414 415 Input Parameters: 416 + n - number of values 417 - ii - array of integers 418 419 Output Parameter: 420 . n - number of non-redundant values 421 422 Level: intermediate 423 424 .seealso: PetscSortReal(), PetscSortIntWithPermutation(), PetscSortInt() 425 @*/ 426 PetscErrorCode PetscSortRemoveDupsMPIInt(PetscInt *n,PetscMPIInt ii[]) 427 { 428 PetscErrorCode ierr; 429 PetscInt i,s = 0,N = *n, b = 0; 430 431 PetscFunctionBegin; 432 ierr = PetscSortMPIInt(N,ii);CHKERRQ(ierr); 433 for (i=0; i<N-1; i++) { 434 if (ii[b+s+1] != ii[b]) { 435 ii[b+1] = ii[b+s+1]; b++; 436 } else s++; 437 } 438 *n = N - s; 439 PetscFunctionReturn(0); 440 } 441 442 /* 443 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 444 Assumes 0 origin for v, number of elements = right+1 (right is index of 445 right-most member). 446 */ 447 static PetscErrorCode PetscSortMPIIntWithArray_Private(PetscMPIInt *v,PetscMPIInt *V,PetscMPIInt right) 448 { 449 PetscErrorCode ierr; 450 PetscMPIInt i,vl,last,tmp; 451 452 PetscFunctionBegin; 453 if (right <= 1) { 454 if (right == 1) { 455 if (v[0] > v[1]) SWAP2(v[0],v[1],V[0],V[1],tmp); 456 } 457 PetscFunctionReturn(0); 458 } 459 SWAP2(v[0],v[right/2],V[0],V[right/2],tmp); 460 vl = v[0]; 461 last = 0; 462 for (i=1; i<=right; i++) { 463 if (v[i] < vl) {last++; SWAP2(v[last],v[i],V[last],V[i],tmp);} 464 } 465 SWAP2(v[0],v[last],V[0],V[last],tmp); 466 ierr = PetscSortMPIIntWithArray_Private(v,V,last-1);CHKERRQ(ierr); 467 ierr = PetscSortMPIIntWithArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 468 PetscFunctionReturn(0); 469 } 470 471 /*@ 472 PetscSortMPIIntWithArray - Sorts an array of integers in place in increasing order; 473 changes a second array to match the sorted first array. 474 475 Not Collective 476 477 Input Parameters: 478 + n - number of values 479 . i - array of integers 480 - I - second array of integers 481 482 Level: intermediate 483 484 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt() 485 @*/ 486 PetscErrorCode PetscSortMPIIntWithArray(PetscMPIInt n,PetscMPIInt i[],PetscMPIInt Ii[]) 487 { 488 PetscErrorCode ierr; 489 PetscMPIInt j,k,tmp,ik; 490 491 PetscFunctionBegin; 492 if (n<8) { 493 for (k=0; k<n; k++) { 494 ik = i[k]; 495 for (j=k+1; j<n; j++) { 496 if (ik > i[j]) { 497 SWAP2(i[k],i[j],Ii[k],Ii[j],tmp); 498 ik = i[k]; 499 } 500 } 501 } 502 } else { 503 ierr = PetscSortMPIIntWithArray_Private(i,Ii,n-1);CHKERRQ(ierr); 504 } 505 PetscFunctionReturn(0); 506 } 507 508 /* -----------------------------------------------------------------------*/ 509 #define SWAP2MPIIntInt(a,b,c,d,t1,t2) {t1=a;a=b;b=t1;t2=c;c=d;d=t2;} 510 511 /* 512 A simple version of quicksort; taken from Kernighan and Ritchie, page 87. 513 Assumes 0 origin for v, number of elements = right+1 (right is index of 514 right-most member). 515 */ 516 static PetscErrorCode PetscSortMPIIntWithIntArray_Private(PetscMPIInt *v,PetscInt *V,PetscMPIInt right) 517 { 518 PetscErrorCode ierr; 519 PetscMPIInt i,vl,last,t1; 520 PetscInt t2; 521 522 PetscFunctionBegin; 523 if (right <= 1) { 524 if (right == 1) { 525 if (v[0] > v[1]) SWAP2MPIIntInt(v[0],v[1],V[0],V[1],t1,t2); 526 } 527 PetscFunctionReturn(0); 528 } 529 SWAP2MPIIntInt(v[0],v[right/2],V[0],V[right/2],t1,t2); 530 vl = v[0]; 531 last = 0; 532 for (i=1; i<=right; i++) { 533 if (v[i] < vl) {last++; SWAP2MPIIntInt(v[last],v[i],V[last],V[i],t1,t2);} 534 } 535 SWAP2MPIIntInt(v[0],v[last],V[0],V[last],t1,t2); 536 ierr = PetscSortMPIIntWithIntArray_Private(v,V,last-1);CHKERRQ(ierr); 537 ierr = PetscSortMPIIntWithIntArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 538 PetscFunctionReturn(0); 539 } 540 541 /*@ 542 PetscSortMPIIntWithIntArray - Sorts an array of MPI integers in place in increasing order; 543 changes a second array of Petsc intergers to match the sorted first array. 544 545 Not Collective 546 547 Input Parameters: 548 + n - number of values 549 . i - array of MPI integers 550 - I - second array of Petsc integers 551 552 Level: intermediate 553 554 Notes: this routine is useful when one needs to sort MPI ranks with other integer arrays. 555 556 .seealso: PetscSortMPIIntWithArray() 557 @*/ 558 PetscErrorCode PetscSortMPIIntWithIntArray(PetscMPIInt n,PetscMPIInt i[],PetscInt Ii[]) 559 { 560 PetscErrorCode ierr; 561 PetscMPIInt j,k,t1,ik; 562 PetscInt t2; 563 564 PetscFunctionBegin; 565 if (n<8) { 566 for (k=0; k<n; k++) { 567 ik = i[k]; 568 for (j=k+1; j<n; j++) { 569 if (ik > i[j]) { 570 SWAP2MPIIntInt(i[k],i[j],Ii[k],Ii[j],t1,t2); 571 ik = i[k]; 572 } 573 } 574 } 575 } else { 576 ierr = PetscSortMPIIntWithIntArray_Private(i,Ii,n-1);CHKERRQ(ierr); 577 } 578 PetscFunctionReturn(0); 579 } 580 581 /* -----------------------------------------------------------------------*/ 582 #define SWAP2IntScalar(a,b,c,d,t,ts) {t=a;a=b;b=t;ts=c;c=d;d=ts;} 583 584 /* 585 Modified from PetscSortIntWithArray_Private(). 586 */ 587 static PetscErrorCode PetscSortIntWithScalarArray_Private(PetscInt *v,PetscScalar *V,PetscInt right) 588 { 589 PetscErrorCode ierr; 590 PetscInt i,vl,last,tmp; 591 PetscScalar stmp; 592 593 PetscFunctionBegin; 594 if (right <= 1) { 595 if (right == 1) { 596 if (v[0] > v[1]) SWAP2IntScalar(v[0],v[1],V[0],V[1],tmp,stmp); 597 } 598 PetscFunctionReturn(0); 599 } 600 SWAP2IntScalar(v[0],v[right/2],V[0],V[right/2],tmp,stmp); 601 vl = v[0]; 602 last = 0; 603 for (i=1; i<=right; i++) { 604 if (v[i] < vl) {last++; SWAP2IntScalar(v[last],v[i],V[last],V[i],tmp,stmp);} 605 } 606 SWAP2IntScalar(v[0],v[last],V[0],V[last],tmp,stmp); 607 ierr = PetscSortIntWithScalarArray_Private(v,V,last-1);CHKERRQ(ierr); 608 ierr = PetscSortIntWithScalarArray_Private(v+last+1,V+last+1,right-(last+1));CHKERRQ(ierr); 609 PetscFunctionReturn(0); 610 } 611 612 /*@ 613 PetscSortIntWithScalarArray - Sorts an array of integers in place in increasing order; 614 changes a second SCALAR array to match the sorted first INTEGER array. 615 616 Not Collective 617 618 Input Parameters: 619 + n - number of values 620 . i - array of integers 621 - I - second array of scalars 622 623 Level: intermediate 624 625 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 626 @*/ 627 PetscErrorCode PetscSortIntWithScalarArray(PetscInt n,PetscInt i[],PetscScalar Ii[]) 628 { 629 PetscErrorCode ierr; 630 PetscInt j,k,tmp,ik; 631 PetscScalar stmp; 632 633 PetscFunctionBegin; 634 if (n<8) { 635 for (k=0; k<n; k++) { 636 ik = i[k]; 637 for (j=k+1; j<n; j++) { 638 if (ik > i[j]) { 639 SWAP2IntScalar(i[k],i[j],Ii[k],Ii[j],tmp,stmp); 640 ik = i[k]; 641 } 642 } 643 } 644 } else { 645 ierr = PetscSortIntWithScalarArray_Private(i,Ii,n-1);CHKERRQ(ierr); 646 } 647 PetscFunctionReturn(0); 648 } 649 650 #define SWAP2IntData(a,b,c,d,t,td,siz) \ 651 do { \ 652 PetscErrorCode _ierr; \ 653 t=a;a=b;b=t; \ 654 _ierr = PetscMemcpy(td,c,siz);CHKERRQ(_ierr); \ 655 _ierr = PetscMemcpy(c,d,siz);CHKERRQ(_ierr); \ 656 _ierr = PetscMemcpy(d,td,siz);CHKERRQ(_ierr); \ 657 } while(0) 658 659 /* 660 Modified from PetscSortIntWithArray_Private(). 661 */ 662 static PetscErrorCode PetscSortIntWithDataArray_Private(PetscInt *v,char *V,PetscInt right,size_t size,void *work) 663 { 664 PetscErrorCode ierr; 665 PetscInt i,vl,last,tmp; 666 667 PetscFunctionBegin; 668 if (right <= 1) { 669 if (right == 1) { 670 if (v[0] > v[1]) SWAP2IntData(v[0],v[1],V,V+size,tmp,work,size); 671 } 672 PetscFunctionReturn(0); 673 } 674 SWAP2IntData(v[0],v[right/2],V,V+size*(right/2),tmp,work,size); 675 vl = v[0]; 676 last = 0; 677 for (i=1; i<=right; i++) { 678 if (v[i] < vl) {last++; SWAP2IntData(v[last],v[i],V+size*last,V+size*i,tmp,work,size);} 679 } 680 SWAP2IntData(v[0],v[last],V,V + size*last,tmp,work,size); 681 ierr = PetscSortIntWithDataArray_Private(v,V,last-1,size,work);CHKERRQ(ierr); 682 ierr = PetscSortIntWithDataArray_Private(v+last+1,V+size*(last+1),right-(last+1),size,work);CHKERRQ(ierr); 683 PetscFunctionReturn(0); 684 } 685 686 /*@C 687 PetscSortIntWithDataArray - Sorts an array of integers in place in increasing order; 688 changes a second array to match the sorted first INTEGER array. Unlike other sort routines, the user must 689 provide workspace (the size of an element in the data array) to use when sorting. 690 691 Not Collective 692 693 Input Parameters: 694 + n - number of values 695 . i - array of integers 696 . Ii - second array of data 697 . size - sizeof elements in the data array in bytes 698 - work - workspace of "size" bytes used when sorting 699 700 Level: intermediate 701 702 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 703 @*/ 704 PetscErrorCode PetscSortIntWithDataArray(PetscInt n,PetscInt i[],void *Ii,size_t size,void *work) 705 { 706 char *V = (char *) Ii; 707 PetscErrorCode ierr; 708 PetscInt j,k,tmp,ik; 709 710 PetscFunctionBegin; 711 if (n<8) { 712 for (k=0; k<n; k++) { 713 ik = i[k]; 714 for (j=k+1; j<n; j++) { 715 if (ik > i[j]) { 716 SWAP2IntData(i[k],i[j],V+size*k,V+size*j,tmp,work,size); 717 ik = i[k]; 718 } 719 } 720 } 721 } else { 722 ierr = PetscSortIntWithDataArray_Private(i,V,n-1,size,work);CHKERRQ(ierr); 723 } 724 PetscFunctionReturn(0); 725 } 726 727 728 /*@ 729 PetscMergeIntArray - Merges two SORTED integer arrays, removes duplicate elements. 730 731 Not Collective 732 733 Input Parameters: 734 + an - number of values in the first array 735 . aI - first sorted array of integers 736 . bn - number of values in the second array 737 - bI - second array of integers 738 739 Output Parameters: 740 + n - number of values in the merged array 741 - L - merged sorted array, this is allocated if an array is not provided 742 743 Level: intermediate 744 745 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 746 @*/ 747 PetscErrorCode PetscMergeIntArray(PetscInt an,const PetscInt aI[], PetscInt bn, const PetscInt bI[], PetscInt *n, PetscInt **L) 748 { 749 PetscErrorCode ierr; 750 PetscInt *L_ = *L, ak, bk, k; 751 752 if (!L_) { 753 ierr = PetscMalloc1(an+bn, L);CHKERRQ(ierr); 754 L_ = *L; 755 } 756 k = ak = bk = 0; 757 while (ak < an && bk < bn) { 758 if (aI[ak] == bI[bk]) { 759 L_[k] = aI[ak]; 760 ++ak; 761 ++bk; 762 ++k; 763 } else if (aI[ak] < bI[bk]) { 764 L_[k] = aI[ak]; 765 ++ak; 766 ++k; 767 } else { 768 L_[k] = bI[bk]; 769 ++bk; 770 ++k; 771 } 772 } 773 if (ak < an) { 774 ierr = PetscArraycpy(L_+k,aI+ak,an-ak);CHKERRQ(ierr); 775 k += (an-ak); 776 } 777 if (bk < bn) { 778 ierr = PetscArraycpy(L_+k,bI+bk,bn-bk);CHKERRQ(ierr); 779 k += (bn-bk); 780 } 781 *n = k; 782 PetscFunctionReturn(0); 783 } 784 785 /*@ 786 PetscMergeIntArrayPair - Merges two SORTED integer arrays that share NO common values along with an additional array of integers. 787 The additional arrays are the same length as sorted arrays and are merged 788 in the order determined by the merging of the sorted pair. 789 790 Not Collective 791 792 Input Parameters: 793 + an - number of values in the first array 794 . aI - first sorted array of integers 795 . aJ - first additional array of integers 796 . bn - number of values in the second array 797 . bI - second array of integers 798 - bJ - second additional of integers 799 800 Output Parameters: 801 + n - number of values in the merged array (== an + bn) 802 . L - merged sorted array 803 - J - merged additional array 804 805 Notes: 806 if L or J point to non-null arrays then this routine will assume they are of the approproate size and use them, otherwise this routine will allocate space for them 807 Level: intermediate 808 809 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 810 @*/ 811 PetscErrorCode PetscMergeIntArrayPair(PetscInt an,const PetscInt aI[], const PetscInt aJ[], PetscInt bn, const PetscInt bI[], const PetscInt bJ[], PetscInt *n, PetscInt **L, PetscInt **J) 812 { 813 PetscErrorCode ierr; 814 PetscInt n_, *L_, *J_, ak, bk, k; 815 816 PetscFunctionBegin; 817 PetscValidIntPointer(L,8); 818 PetscValidIntPointer(J,9); 819 n_ = an + bn; 820 *n = n_; 821 if (!*L) { 822 ierr = PetscMalloc1(n_, L);CHKERRQ(ierr); 823 } 824 L_ = *L; 825 if (!*J) { 826 ierr = PetscMalloc1(n_, J);CHKERRQ(ierr); 827 } 828 J_ = *J; 829 k = ak = bk = 0; 830 while (ak < an && bk < bn) { 831 if (aI[ak] <= bI[bk]) { 832 L_[k] = aI[ak]; 833 J_[k] = aJ[ak]; 834 ++ak; 835 ++k; 836 } else { 837 L_[k] = bI[bk]; 838 J_[k] = bJ[bk]; 839 ++bk; 840 ++k; 841 } 842 } 843 if (ak < an) { 844 ierr = PetscArraycpy(L_+k,aI+ak,an-ak);CHKERRQ(ierr); 845 ierr = PetscArraycpy(J_+k,aJ+ak,an-ak);CHKERRQ(ierr); 846 k += (an-ak); 847 } 848 if (bk < bn) { 849 ierr = PetscArraycpy(L_+k,bI+bk,bn-bk);CHKERRQ(ierr); 850 ierr = PetscArraycpy(J_+k,bJ+bk,bn-bk);CHKERRQ(ierr); 851 } 852 PetscFunctionReturn(0); 853 } 854 855 /*@ 856 PetscMergeMPIIntArray - Merges two SORTED integer arrays. 857 858 Not Collective 859 860 Input Parameters: 861 + an - number of values in the first array 862 . aI - first sorted array of integers 863 . bn - number of values in the second array 864 - bI - second array of integers 865 866 Output Parameters: 867 + n - number of values in the merged array (<= an + bn) 868 - L - merged sorted array, allocated if address of NULL pointer is passed 869 870 Level: intermediate 871 872 .seealso: PetscSortReal(), PetscSortIntPermutation(), PetscSortInt(), PetscSortIntWithArray() 873 @*/ 874 PetscErrorCode PetscMergeMPIIntArray(PetscInt an,const PetscMPIInt aI[],PetscInt bn,const PetscMPIInt bI[],PetscInt *n,PetscMPIInt **L) 875 { 876 PetscErrorCode ierr; 877 PetscInt ai,bi,k; 878 879 PetscFunctionBegin; 880 if (!*L) {ierr = PetscMalloc1((an+bn),L);CHKERRQ(ierr);} 881 for (ai=0,bi=0,k=0; ai<an || bi<bn; ) { 882 PetscInt t = -1; 883 for ( ; ai<an && (!bn || aI[ai] <= bI[bi]); ai++) (*L)[k++] = t = aI[ai]; 884 for ( ; bi<bn && bI[bi] == t; bi++); 885 for ( ; bi<bn && (!an || bI[bi] <= aI[ai]); bi++) (*L)[k++] = t = bI[bi]; 886 for ( ; ai<an && aI[ai] == t; ai++); 887 } 888 *n = k; 889 PetscFunctionReturn(0); 890 } 891 892 /*@C 893 PetscProcessTree - Prepares tree data to be displayed graphically 894 895 Not Collective 896 897 Input Parameters: 898 + n - number of values 899 . mask - indicates those entries in the tree, location 0 is always masked 900 - parentid - indicates the parent of each entry 901 902 Output Parameters: 903 + Nlevels - the number of levels 904 . Level - for each node tells its level 905 . Levelcnts - the number of nodes on each level 906 . Idbylevel - a list of ids on each of the levels, first level followed by second etc 907 - Column - for each id tells its column index 908 909 Level: developer 910 911 Notes: 912 This code is not currently used 913 914 .seealso: PetscSortReal(), PetscSortIntWithPermutation() 915 @*/ 916 PetscErrorCode PetscProcessTree(PetscInt n,const PetscBool mask[],const PetscInt parentid[],PetscInt *Nlevels,PetscInt **Level,PetscInt **Levelcnt,PetscInt **Idbylevel,PetscInt **Column) 917 { 918 PetscInt i,j,cnt,nmask = 0,nlevels = 0,*level,*levelcnt,levelmax = 0,*workid,*workparentid,tcnt = 0,*idbylevel,*column; 919 PetscErrorCode ierr; 920 PetscBool done = PETSC_FALSE; 921 922 PetscFunctionBegin; 923 if (!mask[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Mask of 0th location must be set"); 924 for (i=0; i<n; i++) { 925 if (mask[i]) continue; 926 if (parentid[i] == i) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Node labeled as own parent"); 927 if (parentid[i] && mask[parentid[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parent is masked"); 928 } 929 930 for (i=0; i<n; i++) { 931 if (!mask[i]) nmask++; 932 } 933 934 /* determine the level in the tree of each node */ 935 ierr = PetscCalloc1(n,&level);CHKERRQ(ierr); 936 937 level[0] = 1; 938 while (!done) { 939 done = PETSC_TRUE; 940 for (i=0; i<n; i++) { 941 if (mask[i]) continue; 942 if (!level[i] && level[parentid[i]]) level[i] = level[parentid[i]] + 1; 943 else if (!level[i]) done = PETSC_FALSE; 944 } 945 } 946 for (i=0; i<n; i++) { 947 level[i]--; 948 nlevels = PetscMax(nlevels,level[i]); 949 } 950 951 /* count the number of nodes on each level and its max */ 952 ierr = PetscCalloc1(nlevels,&levelcnt);CHKERRQ(ierr); 953 for (i=0; i<n; i++) { 954 if (mask[i]) continue; 955 levelcnt[level[i]-1]++; 956 } 957 for (i=0; i<nlevels;i++) levelmax = PetscMax(levelmax,levelcnt[i]); 958 959 /* for each level sort the ids by the parent id */ 960 ierr = PetscMalloc2(levelmax,&workid,levelmax,&workparentid);CHKERRQ(ierr); 961 ierr = PetscMalloc1(nmask,&idbylevel);CHKERRQ(ierr); 962 for (j=1; j<=nlevels;j++) { 963 cnt = 0; 964 for (i=0; i<n; i++) { 965 if (mask[i]) continue; 966 if (level[i] != j) continue; 967 workid[cnt] = i; 968 workparentid[cnt++] = parentid[i]; 969 } 970 /* PetscIntView(cnt,workparentid,0); 971 PetscIntView(cnt,workid,0); 972 ierr = PetscSortIntWithArray(cnt,workparentid,workid);CHKERRQ(ierr); 973 PetscIntView(cnt,workparentid,0); 974 PetscIntView(cnt,workid,0);*/ 975 ierr = PetscArraycpy(idbylevel+tcnt,workid,cnt);CHKERRQ(ierr); 976 tcnt += cnt; 977 } 978 if (tcnt != nmask) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Inconsistent count of unmasked nodes"); 979 ierr = PetscFree2(workid,workparentid);CHKERRQ(ierr); 980 981 /* for each node list its column */ 982 ierr = PetscMalloc1(n,&column);CHKERRQ(ierr); 983 cnt = 0; 984 for (j=0; j<nlevels; j++) { 985 for (i=0; i<levelcnt[j]; i++) { 986 column[idbylevel[cnt++]] = i; 987 } 988 } 989 990 *Nlevels = nlevels; 991 *Level = level; 992 *Levelcnt = levelcnt; 993 *Idbylevel = idbylevel; 994 *Column = column; 995 PetscFunctionReturn(0); 996 } 997