/**********************************ivec.c************************************** SPARSE GATHER-SCATTER PACKAGE: bss_malloc bss_malloc ivec error comm gs queue Author: Henry M. Tufo III e-mail: hmt@cs.brown.edu snail-mail: Division of Applied Mathematics Brown University Providence, RI 02912 Last Modification: 6.21.97 ***********************************ivec.c*************************************/ /**********************************ivec.c************************************** File Description: ----------------- ***********************************ivec.c*************************************/ #include "petsc.h" #include #include #include "const.h" #include "types.h" #include "ivec.h" #include "error.h" #include "comm.h" /* sorting args ivec.c ivec.c ... */ #define SORT_OPT 6 #define SORT_STACK 50000 /* allocate an address and size stack for sorter(s) */ static void *offset_stack[2*SORT_STACK]; static int size_stack[SORT_STACK]; static PTRINT psize_stack[SORT_STACK]; /**********************************ivec.c************************************** Function ivec_dump() Input : Output: Return: Description: ***********************************ivec.c*************************************/ void ivec_dump(int *v, int n, int tag, int tag2, char * s) { int i; printf("%2d %2d %s %2d :: ",tag,tag2,s,my_id); for (i=0;i>3)); return(size); } /**********************************ivec.c************************************** Function ivec_non_uniform() Input : Output: Return: Description: ***********************************ivec.c*************************************/ void ivec_non_uniform(int *arg1, int *arg2, register int n, register int *arg3) { register int i, j, type; /* LATER: if we're really motivated we can sort and then unsort */ for (i=0;i length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ pi = ar+1; pj = ar+size; /* find middle element in list and swap w/ element 1 */ SWAP(*(ar+(size>>1)),*pi) /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ if (*pi > *pj) {SWAP(*pi,*pj)} if (*ar > *pj) {SWAP(*ar,*pj)} else if (*pi > *ar) {SWAP(*(ar),*(ar+1))} /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for(;;) { /* walk up ... and down ... swap if equal to pivot! */ do pi++; while (*pi<*ar); do pj--; while (*pj>*ar); /* if we've crossed we're done */ if (pj= SORT_STACK) {error_msg_fatal("ivec_sort() :: STACK EXHAUSTED!!!");} /* push right hand child iff length > 1 */ if ((*top_s = size-((int) (pi-ar)))) { *(top_a++) = pi; size -= *top_s+2; top_s++; } /* set up for next loop iff there is something to do */ else if (size -= *top_s+2) {;} /* might as well pop - note NR_OPT >=2 ==> we're ok! */ else { ar = *(--top_a); size = *(--top_s); } } /* else sort small list directly then pop another off stack */ else { /* insertion sort for bottom */ for (pj=ar+1;pj<=ar+size;pj++) { temp = *pj; for (pi=pj-1;pi>=ar;pi--) { if (*pi <= temp) break; *(pi+1)=*pi; } *(pi+1)=temp; } /* check to see if stack is exhausted ==> DONE */ if (top_s==bottom_s) return; /* else pop another list from the stack */ ar = *(--top_a); size = *(--top_s); } } } /****************************************************************************** Function: ivec_sort_companion(). Input : offset of list to be sorted, number of elements to be sorted. Output: sorted list (in ascending order). Return: none. Description: stack based (nonrecursive) quicksort w/brute-shell bottom. ******************************************************************************/ void ivec_sort_companion(register int *ar, register int *ar2, register int size) { register int *pi, *pj, temp, temp2; register int **top_a = (int **)offset_stack; register int *top_s = size_stack, *bottom_s = size_stack; register int *pi2, *pj2; register int mid; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ mid = size>>1; pi = ar+1; pj = ar+mid; pi2 = ar2+1; pj2 = ar2+mid; /* find middle element in list and swap w/ element 1 */ SWAP(*pi,*pj) SWAP(*pi2,*pj2) /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ pj = ar+size; pj2 = ar2+size; if (*pi > *pj) {SWAP(*pi,*pj) SWAP(*pi2,*pj2)} if (*ar > *pj) {SWAP(*ar,*pj) SWAP(*ar2,*pj2)} else if (*pi > *ar) {SWAP(*(ar),*(ar+1)) SWAP(*(ar2),*(ar2+1))} /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for(;;) { /* walk up ... and down ... swap if equal to pivot! */ do {pi++; pi2++;} while (*pi<*ar); do {pj--; pj2--;} while (*pj>*ar); /* if we've crossed we're done */ if (pj= SORT_STACK) {error_msg_fatal("ivec_sort_companion() :: STACK EXHAUSTED!!!");} /* push right hand child iff length > 1 */ if ((*top_s = size-((int) (pi-ar)))) { *(top_a++) = pi; *(top_a++) = pi2; size -= *top_s+2; top_s++; } /* set up for next loop iff there is something to do */ else if (size -= *top_s+2) {;} /* might as well pop - note NR_OPT >=2 ==> we're ok! */ else { ar2 = *(--top_a); ar = *(--top_a); size = *(--top_s); } } /* else sort small list directly then pop another off stack */ else { /* insertion sort for bottom */ for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++) { temp = *pj; temp2 = *pj2; for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--) { if (*pi <= temp) break; *(pi+1)=*pi; *(pi2+1)=*pi2; } *(pi+1)=temp; *(pi2+1)=temp2; } /* check to see if stack is exhausted ==> DONE */ if (top_s==bottom_s) return; /* else pop another list from the stack */ ar2 = *(--top_a); ar = *(--top_a); size = *(--top_s); } } } /****************************************************************************** Function: ivec_sort_companion_hack(). Input : offset of list to be sorted, number of elements to be sorted. Output: sorted list (in ascending order). Return: none. Description: stack based (nonrecursive) quicksort w/brute-shell bottom. ******************************************************************************/ void ivec_sort_companion_hack(register int *ar, register int **ar2, register int size) { register int *pi, *pj, temp, *ptr; register int **top_a = (int **)offset_stack; register int *top_s = size_stack, *bottom_s = size_stack; register int **pi2, **pj2; register int mid; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ mid = size>>1; pi = ar+1; pj = ar+mid; pi2 = ar2+1; pj2 = ar2+mid; /* find middle element in list and swap w/ element 1 */ SWAP(*pi,*pj) P_SWAP(*pi2,*pj2) /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ pj = ar+size; pj2 = ar2+size; if (*pi > *pj) {SWAP(*pi,*pj) P_SWAP(*pi2,*pj2)} if (*ar > *pj) {SWAP(*ar,*pj) P_SWAP(*ar2,*pj2)} else if (*pi > *ar) {SWAP(*(ar),*(ar+1)) P_SWAP(*(ar2),*(ar2+1))} /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for(;;) { /* walk up ... and down ... swap if equal to pivot! */ do {pi++; pi2++;} while (*pi<*ar); do {pj--; pj2--;} while (*pj>*ar); /* if we've crossed we're done */ if (pj= SORT_STACK) {error_msg_fatal("ivec_sort_companion_hack() :: STACK EXHAUSTED!!!");} /* push right hand child iff length > 1 */ if ((*top_s = size-((int) (pi-ar)))) { *(top_a++) = pi; *(top_a++) = (int*) pi2; size -= *top_s+2; top_s++; } /* set up for next loop iff there is something to do */ else if (size -= *top_s+2) {;} /* might as well pop - note NR_OPT >=2 ==> we're ok! */ else { ar2 = (int **) *(--top_a); ar = *(--top_a); size = *(--top_s); } } /* else sort small list directly then pop another off stack */ else { /* insertion sort for bottom */ for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++) { temp = *pj; ptr = *pj2; for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--) { if (*pi <= temp) break; *(pi+1)=*pi; *(pi2+1)=*pi2; } *(pi+1)=temp; *(pi2+1)=ptr; } /* check to see if stack is exhausted ==> DONE */ if (top_s==bottom_s) return; /* else pop another list from the stack */ ar2 = (int **)*(--top_a); ar = *(--top_a); size = *(--top_s); } } } /****************************************************************************** Function: SMI_sort(). Input : offset of list to be sorted, number of elements to be sorted. Output: sorted list (in ascending order). Return: none. Description: stack based (nonrecursive) quicksort w/brute-shell bottom. ******************************************************************************/ void SMI_sort(void *ar1, void *ar2, int size, int type) { if (type == SORT_INTEGER) { if (ar2) {ivec_sort_companion((int*)ar1,(int*)ar2,size);} else {ivec_sort((int*)ar1,size);} } else if (type == SORT_INT_PTR) { if (ar2) {ivec_sort_companion_hack((int*)ar1,(int **)ar2,size);} else {ivec_sort((int*)ar1,size);} } else { error_msg_fatal("SMI_sort only does SORT_INTEGER!"); } /* if (type == SORT_REAL) { if (ar2) {rvec_sort_companion(ar2,ar1,size);} else {rvec_sort(ar1,size);} } */ } /**********************************ivec.c************************************** Function ivec_linear_search() Input : Output: Return: Description: ***********************************ivec.c*************************************/ int ivec_linear_search(register int item, register int *list, register int n) { register int tmp = n-1; while (n--) {if (*list++ == item) {return(tmp-n);}} return(-1); } /**********************************ivec.c************************************** Function ivec_binary_search() Input : Output: Return: Description: ***********************************ivec.c*************************************/ int ivec_binary_search(register int item, register int *list, register int rh) { register int mid, lh=0; rh--; while (lh<=rh) { mid = (lh+rh)>>1; if (*(list+mid) == item) {return(mid);} if (*(list+mid) > item) {rh = mid-1;} else {lh = mid+1;} } return(-1); } /**********************************ivec.c************************************** Function rvec_dump Input : Output: Return: Description: ***********************************ivec.c*************************************/ void rvec_dump(REAL *v, int n, int tag, int tag2, char * s) { int i; printf("%2d %2d %s %2d :: ",tag,tag2,s,my_id); for (i=0;i length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ pi = ar+1; pj = ar+size; /* find middle element in list and swap w/ element 1 */ SWAP(*(ar+(size>>1)),*pi) pj = ar+size; /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ if (*pi > *pj) {SWAP(*pi,*pj)} if (*ar > *pj) {SWAP(*ar,*pj)} else if (*pi > *ar) {SWAP(*(ar),*(ar+1))} /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for(;;) { /* walk up ... and down ... swap if equal to pivot! */ do pi++; while (*pi<*ar); do pj--; while (*pj>*ar); /* if we've crossed we're done */ if (pj= SORT_STACK) {error_msg_fatal("\nSTACK EXHAUSTED!!!\n");} /* push right hand child iff length > 1 */ if ((*top_s = size-(pi-ar))) { *(top_a++) = pi; size -= *top_s+2; top_s++; } /* set up for next loop iff there is something to do */ else if (size -= *top_s+2) {;} /* might as well pop - note NR_OPT >=2 ==> we're ok! */ else { ar = *(--top_a); size = *(--top_s); } } /* else sort small list directly then pop another off stack */ else { /* insertion sort for bottom */ for (pj=ar+1;pj<=ar+size;pj++) { temp = *pj; for (pi=pj-1;pi>=ar;pi--) { if (*pi <= temp) break; *(pi+1)=*pi; } *(pi+1)=temp; } /* check to see if stack is exhausted ==> DONE */ if (top_s==bottom_s) return; /* else pop another list from the stack */ ar = *(--top_a); size = *(--top_s); } } } /****************************************************************************** Function: my_sort(). Input : offset of list to be sorted, number of elements to be sorted. Output: sorted list (in ascending order). Return: none. Description: stack based (nonrecursive) quicksort w/brute-shell bottom. ******************************************************************************/ void rvec_sort_companion(register REAL *ar, register int *ar2, register int Size) { register REAL *pi, *pj, temp; register REAL **top_a = (REAL **)offset_stack; register PTRINT *top_s = psize_stack, *bottom_s = psize_stack; register PTRINT size = (PTRINT) Size; register int *pi2, *pj2; register int ptr; register PTRINT mid; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ mid = size>>1; pi = ar+1; pj = ar+mid; pi2 = ar2+1; pj2 = ar2+mid; /* find middle element in list and swap w/ element 1 */ SWAP(*pi,*pj) P_SWAP(*pi2,*pj2) /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ pj = ar+size; pj2 = ar2+size; if (*pi > *pj) {SWAP(*pi,*pj) P_SWAP(*pi2,*pj2)} if (*ar > *pj) {SWAP(*ar,*pj) P_SWAP(*ar2,*pj2)} else if (*pi > *ar) {SWAP(*(ar),*(ar+1)) P_SWAP(*(ar2),*(ar2+1))} /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for(;;) { /* walk up ... and down ... swap if equal to pivot! */ do {pi++; pi2++;} while (*pi<*ar); do {pj--; pj2--;} while (*pj>*ar); /* if we've crossed we're done */ if (pj= SORT_STACK) {error_msg_fatal("\nSTACK EXHAUSTED!!!\n");} /* push right hand child iff length > 1 */ if ((*top_s = size-(pi-ar))) { *(top_a++) = pi; *(top_a++) = (REAL *) pi2; size -= *top_s+2; top_s++; } /* set up for next loop iff there is something to do */ else if (size -= *top_s+2) {;} /* might as well pop - note NR_OPT >=2 ==> we're ok! */ else { ar2 = (int*) *(--top_a); ar = *(--top_a); size = *(--top_s); } } /* else sort small list directly then pop another off stack */ else { /* insertion sort for bottom */ for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++) { temp = *pj; ptr = *pj2; for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--) { if (*pi <= temp) break; *(pi+1)=*pi; *(pi2+1)=*pi2; } *(pi+1)=temp; *(pi2+1)=ptr; } /* check to see if stack is exhausted ==> DONE */ if (top_s==bottom_s) return; /* else pop another list from the stack */ ar2 = (int*) *(--top_a); ar = *(--top_a); size = *(--top_s); } } } /**********************************ivec.c************************************** Function ivec_binary_search() Input : Output: Return: Description: ***********************************ivec.c*************************************/ int rvec_binary_search(register REAL item, register REAL *list, register int rh) { register int mid, lh=0; rh--; while (lh<=rh) { mid = (lh+rh)>>1; if (*(list+mid) == item) {return(mid);} if (*(list+mid) > item) {rh = mid-1;} else {lh = mid+1;} } return(-1); }