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