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