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