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