xref: /petsc/src/ksp/pc/impls/tfs/ivec.c (revision 73e7a55880f7211d317aabb87c8bd5e70ea1847f)
1 
2 /**********************************ivec.c**************************************
3 
4 Author: Henry M. Tufo III
5 
6 e-mail: hmt@cs.brown.edu
7 
8 snail-mail:
9 Division of Applied Mathematics
10 Brown University
11 Providence, RI 02912
12 
13 Last Modification:
14 6.21.97
15 ***********************************ivec.c*************************************/
16 
17 /**********************************ivec.c**************************************
18 File Description:
19 -----------------
20 
21 ***********************************ivec.c*************************************/
22 #include "petsc.h"
23 #include <float.h>
24 #include <limits.h>
25 
26 
27 #include "const.h"
28 #include "types.h"
29 #include "ivec.h"
30 #include "error.h"
31 #include "comm.h"
32 
33 
34 /* sorting args ivec.c ivec.c ... */
35 #define   SORT_OPT	6
36 #define   SORT_STACK	50000
37 
38 
39 /* allocate an address and size stack for sorter(s) */
40 static void *offset_stack[2*SORT_STACK];
41 static int   size_stack[SORT_STACK];
42 static long psize_stack[SORT_STACK];
43 
44 
45 
46 /**********************************ivec.c**************************************
47 Function ivec_dump()
48 
49 Input :
50 Output:
51 Return:
52 Description:
53 ***********************************ivec.c*************************************/
54 void
55 ivec_dump(int *v, int n, int tag, int tag2, char * s)
56 {
57   int i;
58   printf("%2d %2d %s %2d :: ",tag,tag2,s,my_id);
59   for (i=0;i<n;i++)
60     {printf("%2d ",v[i]);}
61   printf("\n");
62   fflush(stdout);
63 }
64 
65 
66 
67 /**********************************ivec.c**************************************
68 Function ivec_lb_ub()
69 
70 Input :
71 Output:
72 Return:
73 Description:
74 ***********************************ivec.c*************************************/
75 void
76 ivec_lb_ub( int *arg1,  int n, int *lb, int *ub)
77 {
78    int min = INT_MAX;
79    int max = INT_MIN;
80 
81   while (n--)
82     {
83      min = PetscMin(min,*arg1);
84      max = PetscMax(max,*arg1);
85      arg1++;
86     }
87 
88   *lb=min;
89   *ub=max;
90 }
91 
92 
93 
94 /**********************************ivec.c**************************************
95 Function ivec_copy()
96 
97 Input :
98 Output:
99 Return:
100 Description:
101 ***********************************ivec.c*************************************/
102 int *ivec_copy( int *arg1,  int *arg2,  int n)
103 {
104   while (n--)  {*arg1++ = *arg2++;}
105   return(arg1);
106 }
107 
108 
109 
110 /**********************************ivec.c**************************************
111 Function ivec_zero()
112 
113 Input :
114 Output:
115 Return:
116 Description:
117 ***********************************ivec.c*************************************/
118 void
119 ivec_zero( int *arg1,  int n)
120 {
121   while (n--)  {*arg1++ = 0;}
122 }
123 
124 
125 
126 /**********************************ivec.c**************************************
127 Function ivec_comp()
128 
129 Input :
130 Output:
131 Return:
132 Description:
133 ***********************************ivec.c*************************************/
134 void
135 ivec_comp( int *arg1,  int n)
136 {
137   while (n--)  {*arg1 = ~*arg1; arg1++;}
138 }
139 
140 
141 
142 /**********************************ivec.c**************************************
143 Function ivec_neg_one()
144 
145 Input :
146 Output:
147 Return:
148 Description:
149 ***********************************ivec.c*************************************/
150 void
151 ivec_neg_one( int *arg1,  int n)
152 {
153   while (n--)  {*arg1++ = -1;}
154 }
155 
156 
157 
158 /**********************************ivec.c**************************************
159 Function ivec_pos_one()
160 
161 Input :
162 Output:
163 Return:
164 Description:
165 ***********************************ivec.c*************************************/
166 void
167 ivec_pos_one( int *arg1,  int n)
168 {
169   while (n--)  {*arg1++ = 1;}
170 }
171 
172 
173 
174 /**********************************ivec.c**************************************
175 Function ivec_c_index()
176 
177 Input :
178 Output:
179 Return:
180 Description:
181 ***********************************ivec.c*************************************/
182 void
183 ivec_c_index( int *arg1,  int n)
184 {
185    int i=0;
186 
187 
188   while (n--)  {*arg1++ = i++;}
189 }
190 
191 
192 
193 /**********************************ivec.c**************************************
194 Function ivec_fortran_index()
195 
196 Input :
197 Output:
198 Return:
199 Description:
200 ***********************************ivec.c*************************************/
201 void
202 ivec_fortran_index( int *arg1,  int n)
203 {
204    int i=0;
205 
206 
207   while (n--)  {*arg1++ = ++i;}
208 }
209 
210 
211 
212 /**********************************ivec.c**************************************
213 Function ivec_set()
214 
215 Input :
216 Output:
217 Return:
218 Description:
219 ***********************************ivec.c*************************************/
220 void
221 ivec_set( int *arg1,  int arg2,  int n)
222 {
223   while (n--)  {*arg1++ = arg2;}
224 }
225 
226 
227 
228 /**********************************ivec.c**************************************
229 Function ivec_cmp()
230 
231 Input :
232 Output:
233 Return:
234 Description:
235 ***********************************ivec.c*************************************/
236 int
237 ivec_cmp( int *arg1,  int *arg2,  int n)
238 {
239   while (n--)  {if (*arg1++ != *arg2++)  {return(FALSE);}}
240   return(TRUE);
241 }
242 
243 
244 
245 /**********************************ivec.c**************************************
246 Function ivec_max()
247 
248 Input :
249 Output:
250 Return:
251 Description:
252 ***********************************ivec.c*************************************/
253 void
254 ivec_max( int *arg1,  int *arg2,  int n)
255 {
256   while (n--)  {*arg1 = PetscMax(*arg1,*arg2); arg1++; arg2++;}
257 }
258 
259 
260 
261 /**********************************ivec.c**************************************
262 Function ivec_min()
263 
264 Input :
265 Output:
266 Return:
267 Description:
268 ***********************************ivec.c*************************************/
269 void
270 ivec_min( int *arg1,  int *arg2,  int n)
271 {
272   while (n--)  {*(arg1) = PetscMin(*arg1,*arg2); arg1++; arg2++;}
273 }
274 
275 
276 
277 /**********************************ivec.c**************************************
278 Function ivec_mult()
279 
280 Input :
281 Output:
282 Return:
283 Description:
284 ***********************************ivec.c*************************************/
285 void
286 ivec_mult( int *arg1,  int *arg2,  int n)
287 {
288   while (n--)  {*arg1++ *= *arg2++;}
289 }
290 
291 
292 
293 /**********************************ivec.c**************************************
294 Function ivec_add()
295 
296 Input :
297 Output:
298 Return:
299 Description:
300 ***********************************ivec.c*************************************/
301 void
302 ivec_add( int *arg1,  int *arg2,  int n)
303 {
304   while (n--)  {*arg1++ += *arg2++;}
305 }
306 
307 
308 
309 /**********************************ivec.c**************************************
310 Function ivec_lxor()
311 
312 Input :
313 Output:
314 Return:
315 Description:
316 ***********************************ivec.c*************************************/
317 void
318 ivec_lxor( int *arg1,  int *arg2,  int n)
319 {
320   while (n--) {*arg1=((*arg1 || *arg2) && !(*arg1 && *arg2)); arg1++; arg2++;}
321 }
322 
323 
324 
325 /**********************************ivec.c**************************************
326 Function ivec_xor()
327 
328 Input :
329 Output:
330 Return:
331 Description:
332 ***********************************ivec.c*************************************/
333 void
334 ivec_xor( int *arg1,  int *arg2,  int n)
335 {
336   while (n--)  {*arg1++ ^= *arg2++;}
337 }
338 
339 
340 
341 /**********************************ivec.c**************************************
342 Function ivec_or()
343 
344 Input :
345 Output:
346 Return:
347 Description:
348 ***********************************ivec.c*************************************/
349 void
350 ivec_or( int *arg1,  int *arg2,  int n)
351 {
352   while (n--)  {*arg1++ |= *arg2++;}
353 }
354 
355 
356 
357 /**********************************ivec.c**************************************
358 Function ivec_lor()
359 
360 Input :
361 Output:
362 Return:
363 Description:
364 ***********************************ivec.c*************************************/
365 void
366 ivec_lor( int *arg1,  int *arg2,  int n)
367 {
368   while (n--)  {*arg1 = (*arg1 || *arg2); arg1++; arg2++;}
369 }
370 
371 
372 
373 /**********************************ivec.c**************************************
374 Function ivec_or3()
375 
376 Input :
377 Output:
378 Return:
379 Description:
380 ***********************************ivec.c*************************************/
381 void
382 ivec_or3( int *arg1,  int *arg2,  int *arg3,
383 	  int n)
384 {
385   while (n--)  {*arg1++ = (*arg2++ | *arg3++);}
386 }
387 
388 
389 
390 /**********************************ivec.c**************************************
391 Function ivec_and()
392 
393 Input :
394 Output:
395 Return:
396 Description:
397 ***********************************ivec.c*************************************/
398 void
399 ivec_and( int *arg1,  int *arg2,  int n)
400 {
401   while (n--)  {*arg1++ &= *arg2++;}
402 }
403 
404 
405 
406 /**********************************ivec.c**************************************
407 Function ivec_land()
408 
409 Input :
410 Output:
411 Return:
412 Description:
413 ***********************************ivec.c*************************************/
414 void
415 ivec_land( int *arg1,  int *arg2,  int n)
416 {
417   while (n--) {*arg1 = (*arg1 && *arg2); arg1++; arg2++;}
418 }
419 
420 
421 
422 /**********************************ivec.c**************************************
423 Function ivec_and3()
424 
425 Input :
426 Output:
427 Return:
428 Description:
429 ***********************************ivec.c*************************************/
430 void
431 ivec_and3( int *arg1,  int *arg2,  int *arg3,
432 	   int n)
433 {
434   while (n--)  {*arg1++ = (*arg2++ & *arg3++);}
435 }
436 
437 
438 
439 /**********************************ivec.c**************************************
440 Function ivec_sum
441 
442 Input :
443 Output:
444 Return:
445 Description:
446 ***********************************ivec.c*************************************/
447 int ivec_sum( int *arg1,  int n)
448 {
449    int tmp = 0;
450 
451 
452   while (n--) {tmp += *arg1++;}
453   return(tmp);
454 }
455 
456 
457 
458 /**********************************ivec.c**************************************
459 Function ivec_reduce_and
460 
461 Input :
462 Output:
463 Return:
464 Description:
465 ***********************************ivec.c*************************************/
466 int ivec_reduce_and( int *arg1,  int n)
467 {
468    int tmp = ALL_ONES;
469 
470 
471   while (n--) {tmp &= *arg1++;}
472   return(tmp);
473 }
474 
475 
476 
477 /**********************************ivec.c**************************************
478 Function ivec_reduce_or
479 
480 Input :
481 Output:
482 Return:
483 Description:
484 ***********************************ivec.c*************************************/
485 int ivec_reduce_or( int *arg1,  int n)
486 {
487    int tmp = 0;
488 
489 
490   while (n--) {tmp |= *arg1++;}
491   return(tmp);
492 }
493 
494 
495 
496 /**********************************ivec.c**************************************
497 Function ivec_prod
498 
499 Input :
500 Output:
501 Return:
502 Description:
503 ***********************************ivec.c*************************************/
504 int ivec_prod( int *arg1,  int n)
505 {
506    int tmp = 1;
507 
508 
509   while (n--)  {tmp *= *arg1++;}
510   return(tmp);
511 }
512 
513 
514 
515 /**********************************ivec.c**************************************
516 Function ivec_u_sum
517 
518 Input :
519 Output:
520 Return:
521 Description:
522 ***********************************ivec.c*************************************/
523 int ivec_u_sum( unsigned *arg1,  int n)
524 {
525    unsigned tmp = 0;
526 
527 
528   while (n--)  {tmp += *arg1++;}
529   return(tmp);
530 }
531 
532 
533 
534 /**********************************ivec.c**************************************
535 Function ivec_lb()
536 
537 Input :
538 Output:
539 Return:
540 Description:
541 ***********************************ivec.c*************************************/
542 int
543 ivec_lb( int *arg1,  int n)
544 {
545    int min = INT_MAX;
546 
547 
548   while (n--)  {min = PetscMin(min,*arg1); arg1++;}
549   return(min);
550 }
551 
552 
553 
554 /**********************************ivec.c**************************************
555 Function ivec_ub()
556 
557 Input :
558 Output:
559 Return:
560 Description:
561 ***********************************ivec.c*************************************/
562 int
563 ivec_ub( int *arg1,  int n)
564 {
565    int max = INT_MIN;
566 
567 
568   while (n--)  {max = PetscMax(max,*arg1); arg1++;}
569   return(max);
570 }
571 
572 
573 
574 /**********************************ivec.c**************************************
575 Function split_buf()
576 
577 Input :
578 Output:
579 Return:
580 Description:
581 
582 assumes that sizeof(int) == 4bytes!!!
583 ***********************************ivec.c*************************************/
584 int
585 ivec_split_buf(int *buf1, int **buf2,  int size)
586 {
587   *buf2 = (buf1 + (size>>3));
588   return(size);
589 }
590 
591 
592 
593 /**********************************ivec.c**************************************
594 Function ivec_non_uniform()
595 
596 Input :
597 Output:
598 Return:
599 Description:
600 ***********************************ivec.c*************************************/
601 void
602 ivec_non_uniform(int *arg1, int *arg2,  int n,  int *arg3)
603 {
604    int i, j, type;
605 
606 
607   /* LATER: if we're really motivated we can sort and then unsort */
608   for (i=0;i<n;)
609     {
610       /* clump 'em for now */
611       j=i+1;
612       type = arg3[i];
613       while ((j<n)&&(arg3[j]==type))
614 	{j++;}
615 
616       /* how many together */
617       j -= i;
618 
619       /* call appropriate ivec function */
620       if (type == GL_MAX)
621 	{ivec_max(arg1,arg2,j);}
622       else if (type == GL_MIN)
623 	{ivec_min(arg1,arg2,j);}
624       else if (type == GL_MULT)
625 	{ivec_mult(arg1,arg2,j);}
626       else if (type == GL_ADD)
627 	{ivec_add(arg1,arg2,j);}
628       else if (type == GL_B_XOR)
629 	{ivec_xor(arg1,arg2,j);}
630       else if (type == GL_B_OR)
631 	{ivec_or(arg1,arg2,j);}
632       else if (type == GL_B_AND)
633 	{ivec_and(arg1,arg2,j);}
634       else if (type == GL_L_XOR)
635 	{ivec_lxor(arg1,arg2,j);}
636       else if (type == GL_L_OR)
637 	{ivec_lor(arg1,arg2,j);}
638       else if (type == GL_L_AND)
639 	{ivec_land(arg1,arg2,j);}
640       else
641 	{error_msg_fatal("unrecognized type passed to ivec_non_uniform()!");}
642 
643       arg1+=j; arg2+=j; i+=j;
644     }
645 }
646 
647 
648 
649 /**********************************ivec.c**************************************
650 Function ivec_addr()
651 
652 Input :
653 Output:
654 Return:
655 Description:
656 ***********************************ivec.c*************************************/
657 vfp ivec_fct_addr( int type)
658 {
659   if (type == NON_UNIFORM)
660     {return((void (*)(void*, void *, int, ...))&ivec_non_uniform);}
661   else if (type == GL_MAX)
662     {return((void (*)(void*, void *, int, ...))&ivec_max);}
663   else if (type == GL_MIN)
664     {return((void (*)(void*, void *, int, ...))&ivec_min);}
665   else if (type == GL_MULT)
666     {return((void (*)(void*, void *, int, ...))&ivec_mult);}
667   else if (type == GL_ADD)
668     {return((void (*)(void*, void *, int, ...))&ivec_add);}
669   else if (type == GL_B_XOR)
670     {return((void (*)(void*, void *, int, ...))&ivec_xor);}
671   else if (type == GL_B_OR)
672     {return((void (*)(void*, void *, int, ...))&ivec_or);}
673   else if (type == GL_B_AND)
674     {return((void (*)(void*, void *, int, ...))&ivec_and);}
675   else if (type == GL_L_XOR)
676     {return((void (*)(void*, void *, int, ...))&ivec_lxor);}
677   else if (type == GL_L_OR)
678     {return((void (*)(void*, void *, int, ...))&ivec_lor);}
679   else if (type == GL_L_AND)
680     {return((void (*)(void*, void *, int, ...))&ivec_land);}
681 
682   /* catch all ... not good if we get here */
683   return(NULL);
684 }
685 
686 
687 /**********************************ivec.c**************************************
688 Function ct_bits()
689 
690 Input :
691 Output:
692 Return:
693 Description: MUST FIX THIS!!!
694 ***********************************ivec.c*************************************/
695 #if defined(notusing)
696 static
697 int
698 ivec_ct_bits( int *ptr,  int n)
699 {
700    int tmp=0;
701 
702 
703   /* should expand to full 32 bit */
704   while (n--)
705     {
706       if (*ptr&128) {tmp++;}
707       if (*ptr&64)  {tmp++;}
708       if (*ptr&32)  {tmp++;}
709       if (*ptr&16)  {tmp++;}
710       if (*ptr&8)   {tmp++;}
711       if (*ptr&4)   {tmp++;}
712       if (*ptr&2)   {tmp++;}
713       if (*ptr&1)   {tmp++;}
714       ptr++;
715     }
716 
717   return(tmp);
718 }
719 #endif
720 
721 
722 /******************************************************************************
723 Function: ivec_sort().
724 
725 Input : offset of list to be sorted, number of elements to be sorted.
726 Output: sorted list (in ascending order).
727 Return: none.
728 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
729 ******************************************************************************/
730 void
731 ivec_sort( int *ar,  int size)
732 {
733    int *pi, *pj, temp;
734    int **top_a = (int **) offset_stack;
735    int *top_s = size_stack, *bottom_s = size_stack;
736 
737 
738   /* we're really interested in the offset of the last element */
739   /* ==> length of the list is now size + 1                    */
740   size--;
741 
742   /* do until we're done ... return when stack is exhausted */
743   for (;;)
744     {
745       /* if list is large enough use quicksort partition exchange code */
746       if (size > SORT_OPT)
747 	{
748 	  /* start up pointer at element 1 and down at size     */
749 	  pi = ar+1;
750 	  pj = ar+size;
751 
752 	  /* find middle element in list and swap w/ element 1 */
753 	  SWAP(*(ar+(size>>1)),*pi)
754 
755 	  /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
756 	  /* note ==> pivot_value in index 0                   */
757 	  if (*pi > *pj)
758 	    {SWAP(*pi,*pj)}
759 	  if (*ar > *pj)
760 	    {SWAP(*ar,*pj)}
761 	  else if (*pi > *ar)
762 	    {SWAP(*(ar),*(ar+1))}
763 
764 	  /* partition about pivot_value ...  	                    */
765 	  /* note lists of length 2 are not guaranteed to be sorted */
766 	  for(;;)
767 	    {
768 	      /* walk up ... and down ... swap if equal to pivot! */
769 	      do pi++; while (*pi<*ar);
770 	      do pj--; while (*pj>*ar);
771 
772 	      /* if we've crossed we're done */
773 	      if (pj<pi) break;
774 
775 	      /* else swap */
776 	      SWAP(*pi,*pj)
777 	    }
778 
779 	  /* place pivot_value in it's correct location */
780 	  SWAP(*ar,*pj)
781 
782 	  /* test stack_size to see if we've exhausted our stack */
783 	  if (top_s-bottom_s >= SORT_STACK)
784 	    {error_msg_fatal("ivec_sort() :: STACK EXHAUSTED!!!");}
785 
786 	  /* push right hand child iff length > 1 */
787 	  if ((*top_s = size-((int) (pi-ar))))
788 	    {
789 	      *(top_a++) = pi;
790 	      size -= *top_s+2;
791 	      top_s++;
792 	    }
793 	  /* set up for next loop iff there is something to do */
794 	  else if (size -= *top_s+2)
795 	    {;}
796 	  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
797 	  else
798 	    {
799 	      ar = *(--top_a);
800 	      size = *(--top_s);
801 	    }
802 	}
803 
804       /* else sort small list directly then pop another off stack */
805       else
806 	{
807 	  /* insertion sort for bottom */
808           for (pj=ar+1;pj<=ar+size;pj++)
809             {
810               temp = *pj;
811               for (pi=pj-1;pi>=ar;pi--)
812                 {
813                   if (*pi <= temp) break;
814                   *(pi+1)=*pi;
815                 }
816               *(pi+1)=temp;
817 	    }
818 
819 	  /* check to see if stack is exhausted ==> DONE */
820 	  if (top_s==bottom_s) return;
821 
822 	  /* else pop another list from the stack */
823 	  ar = *(--top_a);
824 	  size = *(--top_s);
825 	}
826     }
827 }
828 
829 
830 
831 /******************************************************************************
832 Function: ivec_sort_companion().
833 
834 Input : offset of list to be sorted, number of elements to be sorted.
835 Output: sorted list (in ascending order).
836 Return: none.
837 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
838 ******************************************************************************/
839 void
840 ivec_sort_companion( int *ar,  int *ar2,  int size)
841 {
842    int *pi, *pj, temp, temp2;
843    int **top_a = (int **)offset_stack;
844    int *top_s = size_stack, *bottom_s = size_stack;
845    int *pi2, *pj2;
846    int mid;
847 
848 
849   /* we're really interested in the offset of the last element */
850   /* ==> length of the list is now size + 1                    */
851   size--;
852 
853   /* do until we're done ... return when stack is exhausted */
854   for (;;)
855     {
856       /* if list is large enough use quicksort partition exchange code */
857       if (size > SORT_OPT)
858 	{
859 	  /* start up pointer at element 1 and down at size     */
860 	  mid = size>>1;
861 	  pi = ar+1;
862 	  pj = ar+mid;
863 	  pi2 = ar2+1;
864 	  pj2 = ar2+mid;
865 
866 	  /* find middle element in list and swap w/ element 1 */
867 	  SWAP(*pi,*pj)
868 	  SWAP(*pi2,*pj2)
869 
870 	  /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
871 	  /* note ==> pivot_value in index 0                   */
872 	  pj = ar+size;
873 	  pj2 = ar2+size;
874 	  if (*pi > *pj)
875 	    {SWAP(*pi,*pj) SWAP(*pi2,*pj2)}
876 	  if (*ar > *pj)
877 	    {SWAP(*ar,*pj) SWAP(*ar2,*pj2)}
878 	  else if (*pi > *ar)
879 	    {SWAP(*(ar),*(ar+1)) SWAP(*(ar2),*(ar2+1))}
880 
881 	  /* partition about pivot_value ...  	                    */
882 	  /* note lists of length 2 are not guaranteed to be sorted */
883 	  for(;;)
884 	    {
885 	      /* walk up ... and down ... swap if equal to pivot! */
886 	      do {pi++; pi2++;} while (*pi<*ar);
887 	      do {pj--; pj2--;} while (*pj>*ar);
888 
889 	      /* if we've crossed we're done */
890 	      if (pj<pi) break;
891 
892 	      /* else swap */
893 	      SWAP(*pi,*pj)
894 	      SWAP(*pi2,*pj2)
895 	    }
896 
897 	  /* place pivot_value in it's correct location */
898 	  SWAP(*ar,*pj)
899 	  SWAP(*ar2,*pj2)
900 
901 	  /* test stack_size to see if we've exhausted our stack */
902 	  if (top_s-bottom_s >= SORT_STACK)
903 	    {error_msg_fatal("ivec_sort_companion() :: STACK EXHAUSTED!!!");}
904 
905 	  /* push right hand child iff length > 1 */
906 	  if ((*top_s = size-((int) (pi-ar))))
907 	    {
908 	      *(top_a++) = pi;
909 	      *(top_a++) = pi2;
910 	      size -= *top_s+2;
911 	      top_s++;
912 	    }
913 	  /* set up for next loop iff there is something to do */
914 	  else if (size -= *top_s+2)
915 	    {;}
916 	  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
917 	  else
918 	    {
919 	      ar2 = *(--top_a);
920 	      ar  = *(--top_a);
921 	      size = *(--top_s);
922 	    }
923 	}
924 
925       /* else sort small list directly then pop another off stack */
926       else
927 	{
928 	  /* insertion sort for bottom */
929           for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++)
930             {
931               temp = *pj;
932               temp2 = *pj2;
933               for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--)
934                 {
935                   if (*pi <= temp) break;
936                   *(pi+1)=*pi;
937                   *(pi2+1)=*pi2;
938                 }
939               *(pi+1)=temp;
940               *(pi2+1)=temp2;
941 	    }
942 
943 	  /* check to see if stack is exhausted ==> DONE */
944 	  if (top_s==bottom_s) return;
945 
946 	  /* else pop another list from the stack */
947 	  ar2 = *(--top_a);
948 	  ar  = *(--top_a);
949 	  size = *(--top_s);
950 	}
951     }
952 }
953 
954 
955 
956 /******************************************************************************
957 Function: ivec_sort_companion_hack().
958 
959 Input : offset of list to be sorted, number of elements to be sorted.
960 Output: sorted list (in ascending order).
961 Return: none.
962 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
963 ******************************************************************************/
964 void
965 ivec_sort_companion_hack( int *ar,  int **ar2,
966 			  int size)
967 {
968    int *pi, *pj, temp, *ptr;
969    int **top_a = (int **)offset_stack;
970    int *top_s = size_stack, *bottom_s = size_stack;
971    int **pi2, **pj2;
972    int mid;
973 
974 
975   /* we're really interested in the offset of the last element */
976   /* ==> length of the list is now size + 1                    */
977   size--;
978 
979   /* do until we're done ... return when stack is exhausted */
980   for (;;)
981     {
982       /* if list is large enough use quicksort partition exchange code */
983       if (size > SORT_OPT)
984 	{
985 	  /* start up pointer at element 1 and down at size     */
986 	  mid = size>>1;
987 	  pi = ar+1;
988 	  pj = ar+mid;
989 	  pi2 = ar2+1;
990 	  pj2 = ar2+mid;
991 
992 	  /* find middle element in list and swap w/ element 1 */
993 	  SWAP(*pi,*pj)
994 	  P_SWAP(*pi2,*pj2)
995 
996 	  /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
997 	  /* note ==> pivot_value in index 0                   */
998 	  pj = ar+size;
999 	  pj2 = ar2+size;
1000 	  if (*pi > *pj)
1001 	    {SWAP(*pi,*pj) P_SWAP(*pi2,*pj2)}
1002 	  if (*ar > *pj)
1003 	    {SWAP(*ar,*pj) P_SWAP(*ar2,*pj2)}
1004 	  else if (*pi > *ar)
1005 	    {SWAP(*(ar),*(ar+1)) P_SWAP(*(ar2),*(ar2+1))}
1006 
1007 	  /* partition about pivot_value ...  	                    */
1008 	  /* note lists of length 2 are not guaranteed to be sorted */
1009 	  for(;;)
1010 	    {
1011 	      /* walk up ... and down ... swap if equal to pivot! */
1012 	      do {pi++; pi2++;} while (*pi<*ar);
1013 	      do {pj--; pj2--;} while (*pj>*ar);
1014 
1015 	      /* if we've crossed we're done */
1016 	      if (pj<pi) break;
1017 
1018 	      /* else swap */
1019 	      SWAP(*pi,*pj)
1020 	      P_SWAP(*pi2,*pj2)
1021 	    }
1022 
1023 	  /* place pivot_value in it's correct location */
1024 	  SWAP(*ar,*pj)
1025 	  P_SWAP(*ar2,*pj2)
1026 
1027 	  /* test stack_size to see if we've exhausted our stack */
1028 	  if (top_s-bottom_s >= SORT_STACK)
1029          {error_msg_fatal("ivec_sort_companion_hack() :: STACK EXHAUSTED!!!");}
1030 
1031 	  /* push right hand child iff length > 1 */
1032 	  if ((*top_s = size-((int) (pi-ar))))
1033 	    {
1034 	      *(top_a++) = pi;
1035 	      *(top_a++) = (int*) pi2;
1036 	      size -= *top_s+2;
1037 	      top_s++;
1038 	    }
1039 	  /* set up for next loop iff there is something to do */
1040 	  else if (size -= *top_s+2)
1041 	    {;}
1042 	  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
1043 	  else
1044 	    {
1045 	      ar2 = (int **) *(--top_a);
1046 	      ar  = *(--top_a);
1047 	      size = *(--top_s);
1048 	    }
1049 	}
1050 
1051       /* else sort small list directly then pop another off stack */
1052       else
1053 	{
1054 	  /* insertion sort for bottom */
1055           for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++)
1056             {
1057               temp = *pj;
1058               ptr = *pj2;
1059               for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--)
1060                 {
1061                   if (*pi <= temp) break;
1062                   *(pi+1)=*pi;
1063                   *(pi2+1)=*pi2;
1064                 }
1065               *(pi+1)=temp;
1066               *(pi2+1)=ptr;
1067 	    }
1068 
1069 	  /* check to see if stack is exhausted ==> DONE */
1070 	  if (top_s==bottom_s) return;
1071 
1072 	  /* else pop another list from the stack */
1073 	  ar2 = (int **)*(--top_a);
1074 	  ar  = *(--top_a);
1075 	  size = *(--top_s);
1076 	}
1077     }
1078 }
1079 
1080 
1081 
1082 /******************************************************************************
1083 Function: SMI_sort().
1084 Input : offset of list to be sorted, number of elements to be sorted.
1085 Output: sorted list (in ascending order).
1086 Return: none.
1087 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
1088 ******************************************************************************/
1089 void
1090 SMI_sort(void *ar1, void *ar2, int size, int type)
1091 {
1092   if (type == SORT_INTEGER)
1093     {
1094       if (ar2)
1095 	{ivec_sort_companion((int*)ar1,(int*)ar2,size);}
1096       else
1097 	{ivec_sort((int*)ar1,size);}
1098     }
1099   else if (type == SORT_INT_PTR)
1100     {
1101       if (ar2)
1102 	{ivec_sort_companion_hack((int*)ar1,(int **)ar2,size);}
1103       else
1104 	{ivec_sort((int*)ar1,size);}
1105     }
1106 
1107   else
1108     {
1109       error_msg_fatal("SMI_sort only does SORT_INTEGER!");
1110     }
1111 /*
1112   if (type == SORT_REAL)
1113     {
1114       if (ar2)
1115 	{rvec_sort_companion(ar2,ar1,size);}
1116       else
1117 	{rvec_sort(ar1,size);}
1118     }
1119 */
1120 }
1121 
1122 
1123 
1124 /**********************************ivec.c**************************************
1125 Function ivec_linear_search()
1126 
1127 Input :
1128 Output:
1129 Return:
1130 Description:
1131 ***********************************ivec.c*************************************/
1132 int
1133 ivec_linear_search( int item,  int *list,  int n)
1134 {
1135    int tmp = n-1;
1136 
1137   while (n--)  {if (*list++ == item) {return(tmp-n);}}
1138   return(-1);
1139 }
1140 
1141 
1142 
1143 /**********************************ivec.c**************************************
1144 Function ivec_binary_search()
1145 
1146 Input :
1147 Output:
1148 Return:
1149 Description:
1150 ***********************************ivec.c*************************************/
1151 int
1152 ivec_binary_search( int item,  int *list,  int rh)
1153 {
1154    int mid, lh=0;
1155 
1156   rh--;
1157   while (lh<=rh)
1158     {
1159       mid = (lh+rh)>>1;
1160       if (*(list+mid) == item)
1161 	{return(mid);}
1162       if (*(list+mid) > item)
1163 	{rh = mid-1;}
1164       else
1165 	{lh = mid+1;}
1166     }
1167   return(-1);
1168 }
1169 
1170 
1171 
1172 /**********************************ivec.c**************************************
1173 Function rvec_dump
1174 
1175 Input :
1176 Output:
1177 Return:
1178 Description:
1179 ***********************************ivec.c*************************************/
1180 void
1181 rvec_dump(PetscScalar *v, int n, int tag, int tag2, char * s)
1182 {
1183   int i;
1184   printf("%2d %2d %s %2d :: ",tag,tag2,s,my_id);
1185   for (i=0;i<n;i++)
1186     {printf("%f ",v[i]);}
1187   printf("\n");
1188   fflush(stdout);
1189 }
1190 
1191 
1192 
1193 /**********************************ivec.c**************************************
1194 Function rvec_lb_ub()
1195 
1196 Input :
1197 Output:
1198 Return:
1199 Description:
1200 ***********************************ivec.c*************************************/
1201 void
1202 rvec_lb_ub( PetscScalar *arg1,  int n, PetscScalar *lb, PetscScalar *ub)
1203 {
1204    PetscScalar min =  REAL_MAX;
1205    PetscScalar max = -REAL_MAX;
1206 
1207   while (n--)
1208     {
1209      min = PetscMin(min,*arg1);
1210      max = PetscMax(max,*arg1);
1211      arg1++;
1212     }
1213 
1214   *lb=min;
1215   *ub=max;
1216 }
1217 
1218 
1219 
1220 /********************************ivec.c**************************************
1221 Function rvec_copy()
1222 
1223 Input :
1224 Output:
1225 Return:
1226 Description:
1227 *********************************ivec.c*************************************/
1228 void
1229 rvec_copy( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1230 {
1231   while (n--)  {*arg1++ = *arg2++;}
1232 }
1233 
1234 
1235 
1236 /********************************ivec.c**************************************
1237 Function rvec_zero()
1238 
1239 Input :
1240 Output:
1241 Return:
1242 Description:
1243 *********************************ivec.c*************************************/
1244 void
1245 rvec_zero( PetscScalar *arg1,  int n)
1246 {
1247   while (n--)  {*arg1++ = 0.0;}
1248 }
1249 
1250 
1251 
1252 /**********************************ivec.c**************************************
1253 Function rvec_one()
1254 
1255 Input :
1256 Output:
1257 Return:
1258 Description:
1259 ***********************************ivec.c*************************************/
1260 void
1261 rvec_one( PetscScalar *arg1,  int n)
1262 {
1263   while (n--)  {*arg1++ = 1.0;}
1264 }
1265 
1266 
1267 
1268 /**********************************ivec.c**************************************
1269 Function rvec_neg_one()
1270 
1271 Input :
1272 Output:
1273 Return:
1274 Description:
1275 ***********************************ivec.c*************************************/
1276 void
1277 rvec_neg_one( PetscScalar *arg1,  int n)
1278 {
1279   while (n--)  {*arg1++ = -1.0;}
1280 }
1281 
1282 
1283 
1284 /**********************************ivec.c**************************************
1285 Function rvec_set()
1286 
1287 Input :
1288 Output:
1289 Return:
1290 Description:
1291 ***********************************ivec.c*************************************/
1292 void
1293 rvec_set( PetscScalar *arg1,  PetscScalar arg2,  int n)
1294 {
1295   while (n--)  {*arg1++ = arg2;}
1296 }
1297 
1298 
1299 
1300 /**********************************ivec.c**************************************
1301 Function rvec_scale()
1302 
1303 Input :
1304 Output:
1305 Return:
1306 Description:
1307 ***********************************ivec.c*************************************/
1308 void
1309 rvec_scale( PetscScalar *arg1,  PetscScalar arg2,  int n)
1310 {
1311   while (n--)  {*arg1++ *= arg2;}
1312 }
1313 
1314 
1315 
1316 /********************************ivec.c**************************************
1317 Function rvec_add()
1318 
1319 Input :
1320 Output:
1321 Return:
1322 Description:
1323 *********************************ivec.c*************************************/
1324 void
1325 rvec_add( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1326 {
1327   while (n--)  {*arg1++ += *arg2++;}
1328 }
1329 
1330 
1331 
1332 /********************************ivec.c**************************************
1333 Function rvec_dot()
1334 
1335 Input :
1336 Output:
1337 Return:
1338 Description:
1339 *********************************ivec.c*************************************/
1340 PetscScalar
1341 rvec_dot( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1342 {
1343   PetscScalar dot=0.0;
1344 
1345   while (n--)  {dot+= *arg1++ * *arg2++;}
1346 
1347   return(dot);
1348 }
1349 
1350 
1351 
1352 /********************************ivec.c**************************************
1353 Function rvec_axpy()
1354 
1355 Input :
1356 Output:
1357 Return:
1358 Description:
1359 *********************************ivec.c*************************************/
1360 void
1361 rvec_axpy( PetscScalar *arg1,  PetscScalar *arg2,  PetscScalar scale,
1362 	   int n)
1363 {
1364   while (n--)  {*arg1++ += scale * *arg2++;}
1365 }
1366 
1367 
1368 /********************************ivec.c**************************************
1369 Function rvec_mult()
1370 
1371 Input :
1372 Output:
1373 Return:
1374 Description:
1375 *********************************ivec.c*************************************/
1376 void
1377 rvec_mult( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1378 {
1379   while (n--)  {*arg1++ *= *arg2++;}
1380 }
1381 
1382 
1383 
1384 /********************************ivec.c**************************************
1385 Function rvec_max()
1386 
1387 Input :
1388 Output:
1389 Return:
1390 Description:
1391 *********************************ivec.c*************************************/
1392 void
1393 rvec_max( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1394 {
1395   while (n--)  {*arg1 = PetscMax(*arg1,*arg2); arg1++; arg2++;}
1396 }
1397 
1398 
1399 
1400 /********************************ivec.c**************************************
1401 Function rvec_max_abs()
1402 
1403 Input :
1404 Output:
1405 Return:
1406 Description:
1407 *********************************ivec.c*************************************/
1408 void
1409 rvec_max_abs( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1410 {
1411   while (n--)  {*arg1 = MAX_FABS(*arg1,*arg2); arg1++; arg2++;}
1412 }
1413 
1414 
1415 
1416 /********************************ivec.c**************************************
1417 Function rvec_min()
1418 
1419 Input :
1420 Output:
1421 Return:
1422 Description:
1423 *********************************ivec.c*************************************/
1424 void
1425 rvec_min( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1426 {
1427   while (n--)  {*arg1 = PetscMin(*arg1,*arg2); arg1++; arg2++;}
1428 }
1429 
1430 
1431 
1432 /********************************ivec.c**************************************
1433 Function rvec_min_abs()
1434 
1435 Input :
1436 Output:
1437 Return:
1438 Description:
1439 *********************************ivec.c*************************************/
1440 void
1441 rvec_min_abs( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1442 {
1443   while (n--)  {*arg1 = MIN_FABS(*arg1,*arg2); arg1++; arg2++;}
1444 }
1445 
1446 
1447 
1448 /********************************ivec.c**************************************
1449 Function rvec_exists()
1450 
1451 Input :
1452 Output:
1453 Return:
1454 Description:
1455 *********************************ivec.c*************************************/
1456 void
1457 rvec_exists( PetscScalar *arg1,  PetscScalar *arg2,  int n)
1458 {
1459   while (n--)  {*arg1 = EXISTS(*arg1,*arg2); arg1++; arg2++;}
1460 }
1461 
1462 
1463 
1464 /**********************************ivec.c**************************************
1465 Function rvec_non_uniform()
1466 
1467 Input :
1468 Output:
1469 Return:
1470 Description:
1471 ***********************************ivec.c*************************************/
1472 void
1473 rvec_non_uniform(PetscScalar *arg1, PetscScalar *arg2,  int n,  int *arg3)
1474 {
1475    int i, j, type;
1476 
1477 
1478   /* LATER: if we're really motivated we can sort and then unsort */
1479   for (i=0;i<n;)
1480     {
1481       /* clump 'em for now */
1482       j=i+1;
1483       type = arg3[i];
1484       while ((j<n)&&(arg3[j]==type))
1485 	{j++;}
1486 
1487       /* how many together */
1488       j -= i;
1489 
1490       /* call appropriate ivec function */
1491       if (type == GL_MAX)
1492 	{rvec_max(arg1,arg2,j);}
1493       else if (type == GL_MIN)
1494 	{rvec_min(arg1,arg2,j);}
1495       else if (type == GL_MULT)
1496 	{rvec_mult(arg1,arg2,j);}
1497       else if (type == GL_ADD)
1498 	{rvec_add(arg1,arg2,j);}
1499       else if (type == GL_MAX_ABS)
1500 	{rvec_max_abs(arg1,arg2,j);}
1501       else if (type == GL_MIN_ABS)
1502 	{rvec_min_abs(arg1,arg2,j);}
1503       else if (type == GL_EXISTS)
1504 	{rvec_exists(arg1,arg2,j);}
1505       else
1506 	{error_msg_fatal("unrecognized type passed to rvec_non_uniform()!");}
1507 
1508       arg1+=j; arg2+=j; i+=j;
1509     }
1510 }
1511 
1512 
1513 
1514 /**********************************ivec.c**************************************
1515 Function rvec_fct_addr()
1516 
1517 Input :
1518 Output:
1519 Return:
1520 Description:
1521 ***********************************ivec.c*************************************/
1522 vfp rvec_fct_addr( int type)
1523 {
1524   if (type == NON_UNIFORM)
1525     {return((void (*)(void*, void *, int, ...))&rvec_non_uniform);}
1526   else if (type == GL_MAX)
1527     {return((void (*)(void*, void *, int, ...))&rvec_max);}
1528   else if (type == GL_MIN)
1529     {return((void (*)(void*, void *, int, ...))&rvec_min);}
1530   else if (type == GL_MULT)
1531     {return((void (*)(void*, void *, int, ...))&rvec_mult);}
1532   else if (type == GL_ADD)
1533     {return((void (*)(void*, void *, int, ...))&rvec_add);}
1534   else if (type == GL_MAX_ABS)
1535     {return((void (*)(void*, void *, int, ...))&rvec_max_abs);}
1536   else if (type == GL_MIN_ABS)
1537     {return((void (*)(void*, void *, int, ...))&rvec_min_abs);}
1538   else if (type == GL_EXISTS)
1539     {return((void (*)(void*, void *, int, ...))&rvec_exists);}
1540 
1541   /* catch all ... not good if we get here */
1542   return(NULL);
1543 }
1544 
1545 
1546 /******************************************************************************
1547 Function: my_sort().
1548 Input : offset of list to be sorted, number of elements to be sorted.
1549 Output: sorted list (in ascending order).
1550 Return: none.
1551 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
1552 ******************************************************************************/
1553 void
1554 rvec_sort( PetscScalar *ar,  int Size)
1555 {
1556    PetscScalar *pi, *pj, temp;
1557    PetscScalar **top_a = (PetscScalar **)offset_stack;
1558    long *top_s = psize_stack, *bottom_s = psize_stack;
1559    long size = (long) Size;
1560 
1561   /* we're really interested in the offset of the last element */
1562   /* ==> length of the list is now size + 1                    */
1563   size--;
1564 
1565   /* do until we're done ... return when stack is exhausted */
1566   for (;;)
1567     {
1568       /* if list is large enough use quicksort partition exchange code */
1569       if (size > SORT_OPT)
1570 	{
1571 	  /* start up pointer at element 1 and down at size     */
1572 	  pi = ar+1;
1573 	  pj = ar+size;
1574 
1575 	  /* find middle element in list and swap w/ element 1 */
1576 	  SWAP(*(ar+(size>>1)),*pi)
1577 
1578 	  pj = ar+size;
1579 
1580 	  /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
1581 	  /* note ==> pivot_value in index 0                   */
1582 	  if (*pi > *pj)
1583 	    {SWAP(*pi,*pj)}
1584 	  if (*ar > *pj)
1585 	    {SWAP(*ar,*pj)}
1586 	  else if (*pi > *ar)
1587 	    {SWAP(*(ar),*(ar+1))}
1588 
1589 	  /* partition about pivot_value ...  	                    */
1590 	  /* note lists of length 2 are not guaranteed to be sorted */
1591 	  for(;;)
1592 	    {
1593 	      /* walk up ... and down ... swap if equal to pivot! */
1594 	      do pi++; while (*pi<*ar);
1595 	      do pj--; while (*pj>*ar);
1596 
1597 	      /* if we've crossed we're done */
1598 	      if (pj<pi) break;
1599 
1600 	      /* else swap */
1601 	      SWAP(*pi,*pj)
1602 	    }
1603 
1604 	  /* place pivot_value in it's correct location */
1605 	  SWAP(*ar,*pj)
1606 
1607 	  /* test stack_size to see if we've exhausted our stack */
1608 	  if (top_s-bottom_s >= SORT_STACK)
1609 	    {error_msg_fatal("\nSTACK EXHAUSTED!!!\n");}
1610 
1611 	  /* push right hand child iff length > 1 */
1612 	  if ((*top_s = size-(pi-ar)))
1613 	    {
1614 	      *(top_a++) = pi;
1615 	      size -= *top_s+2;
1616 	      top_s++;
1617 	    }
1618 	  /* set up for next loop iff there is something to do */
1619 	  else if (size -= *top_s+2)
1620 	    {;}
1621 	  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
1622 	  else
1623 	    {
1624 	      ar = *(--top_a);
1625 	      size = *(--top_s);
1626 	    }
1627 	}
1628 
1629       /* else sort small list directly then pop another off stack */
1630       else
1631 	{
1632 	  /* insertion sort for bottom */
1633           for (pj=ar+1;pj<=ar+size;pj++)
1634             {
1635               temp = *pj;
1636               for (pi=pj-1;pi>=ar;pi--)
1637                 {
1638                   if (*pi <= temp) break;
1639                   *(pi+1)=*pi;
1640                 }
1641               *(pi+1)=temp;
1642 	    }
1643 
1644 	  /* check to see if stack is exhausted ==> DONE */
1645 	  if (top_s==bottom_s) return;
1646 
1647 	  /* else pop another list from the stack */
1648 	  ar = *(--top_a);
1649 	  size = *(--top_s);
1650 	}
1651     }
1652 }
1653 
1654 
1655 
1656 /******************************************************************************
1657 Function: my_sort().
1658 Input : offset of list to be sorted, number of elements to be sorted.
1659 Output: sorted list (in ascending order).
1660 Return: none.
1661 Description: stack based (nonrecursive) quicksort w/brute-shell bottom.
1662 ******************************************************************************/
1663 void
1664 rvec_sort_companion( PetscScalar *ar,  int *ar2,  int Size)
1665 {
1666    PetscScalar *pi, *pj, temp;
1667    PetscScalar **top_a = (PetscScalar **)offset_stack;
1668    long *top_s = psize_stack, *bottom_s = psize_stack;
1669    long size = (long) Size;
1670 
1671    int *pi2, *pj2;
1672    int ptr;
1673    long mid;
1674 
1675 
1676   /* we're really interested in the offset of the last element */
1677   /* ==> length of the list is now size + 1                    */
1678   size--;
1679 
1680   /* do until we're done ... return when stack is exhausted */
1681   for (;;)
1682     {
1683       /* if list is large enough use quicksort partition exchange code */
1684       if (size > SORT_OPT)
1685 	{
1686 	  /* start up pointer at element 1 and down at size     */
1687 	  mid = size>>1;
1688 	  pi = ar+1;
1689 	  pj = ar+mid;
1690 	  pi2 = ar2+1;
1691 	  pj2 = ar2+mid;
1692 
1693 	  /* find middle element in list and swap w/ element 1 */
1694 	  SWAP(*pi,*pj)
1695 	  P_SWAP(*pi2,*pj2)
1696 
1697 	  /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
1698 	  /* note ==> pivot_value in index 0                   */
1699 	  pj = ar+size;
1700 	  pj2 = ar2+size;
1701 	  if (*pi > *pj)
1702 	    {SWAP(*pi,*pj) P_SWAP(*pi2,*pj2)}
1703 	  if (*ar > *pj)
1704 	    {SWAP(*ar,*pj) P_SWAP(*ar2,*pj2)}
1705 	  else if (*pi > *ar)
1706 	    {SWAP(*(ar),*(ar+1)) P_SWAP(*(ar2),*(ar2+1))}
1707 
1708 	  /* partition about pivot_value ...  	                    */
1709 	  /* note lists of length 2 are not guaranteed to be sorted */
1710 	  for(;;)
1711 	    {
1712 	      /* walk up ... and down ... swap if equal to pivot! */
1713 	      do {pi++; pi2++;} while (*pi<*ar);
1714 	      do {pj--; pj2--;} while (*pj>*ar);
1715 
1716 	      /* if we've crossed we're done */
1717 	      if (pj<pi) break;
1718 
1719 	      /* else swap */
1720 	      SWAP(*pi,*pj)
1721 	      P_SWAP(*pi2,*pj2)
1722 	    }
1723 
1724 	  /* place pivot_value in it's correct location */
1725 	  SWAP(*ar,*pj)
1726 	  P_SWAP(*ar2,*pj2)
1727 
1728 	  /* test stack_size to see if we've exhausted our stack */
1729 	  if (top_s-bottom_s >= SORT_STACK)
1730 	    {error_msg_fatal("\nSTACK EXHAUSTED!!!\n");}
1731 
1732 	  /* push right hand child iff length > 1 */
1733 	  if ((*top_s = size-(pi-ar)))
1734 	    {
1735 	      *(top_a++) = pi;
1736 	      *(top_a++) = (PetscScalar *) pi2;
1737 	      size -= *top_s+2;
1738 	      top_s++;
1739 	    }
1740 	  /* set up for next loop iff there is something to do */
1741 	  else if (size -= *top_s+2)
1742 	    {;}
1743 	  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
1744 	  else
1745 	    {
1746 	      ar2 = (int*) *(--top_a);
1747 	      ar  = *(--top_a);
1748 	      size = *(--top_s);
1749 	    }
1750 	}
1751 
1752       /* else sort small list directly then pop another off stack */
1753       else
1754 	{
1755 	  /* insertion sort for bottom */
1756           for (pj=ar+1, pj2=ar2+1;pj<=ar+size;pj++,pj2++)
1757             {
1758               temp = *pj;
1759               ptr = *pj2;
1760               for (pi=pj-1,pi2=pj2-1;pi>=ar;pi--,pi2--)
1761                 {
1762                   if (*pi <= temp) break;
1763                   *(pi+1)=*pi;
1764                   *(pi2+1)=*pi2;
1765                 }
1766               *(pi+1)=temp;
1767               *(pi2+1)=ptr;
1768 	    }
1769 
1770 	  /* check to see if stack is exhausted ==> DONE */
1771 	  if (top_s==bottom_s) return;
1772 
1773 	  /* else pop another list from the stack */
1774 	  ar2 = (int*) *(--top_a);
1775 	  ar  = *(--top_a);
1776 	  size = *(--top_s);
1777 	}
1778     }
1779 }
1780 
1781 
1782 
1783 
1784 
1785 /**********************************ivec.c**************************************
1786 Function ivec_binary_search()
1787 
1788 Input :
1789 Output:
1790 Return:
1791 Description:
1792 ***********************************ivec.c*************************************/
1793 int
1794 rvec_binary_search( PetscScalar item,  PetscScalar *list,  int rh)
1795 {
1796   int mid, lh=0;
1797 
1798   rh--;
1799   while (lh<=rh)
1800     {
1801       mid = (lh+rh)>>1;
1802       if (*(list+mid) == item)
1803 	{return(mid);}
1804       if (*(list+mid) > item)
1805 	{rh = mid-1;}
1806       else
1807 	{lh = mid+1;}
1808     }
1809   return(-1);
1810 }
1811 
1812 
1813 
1814 
1815 
1816