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