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