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