xref: /petsc/src/ksp/pc/impls/tfs/ivec.c (revision 2b8d69ca7ea5fe9190df62c1dce3bbd66fce84dd)
1 
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 #include <../src/ksp/pc/impls/tfs/tfs.h>
19 
20 /* sorting args ivec.c ivec.c ... */
21 #define   SORT_OPT     6
22 #define   SORT_STACK   50000
23 
24 
25 /* allocate an address and size stack for sorter(s) */
26 static void     *offset_stack[2*SORT_STACK];
27 static PetscInt size_stack[SORT_STACK];
28 
29 /***********************************ivec.c*************************************/
30 PetscInt *PCTFS_ivec_copy(PetscInt *arg1, PetscInt *arg2, PetscInt n)
31 {
32   while (n--) *arg1++ = *arg2++;
33   return(arg1);
34 }
35 
36 /***********************************ivec.c*************************************/
37 PetscErrorCode PCTFS_ivec_zero(PetscInt *arg1, PetscInt n)
38 {
39   PetscFunctionBegin;
40   while (n--) *arg1++ = 0;
41   PetscFunctionReturn(0);
42 }
43 
44 /***********************************ivec.c*************************************/
45 PetscErrorCode PCTFS_ivec_set(PetscInt *arg1, PetscInt arg2, PetscInt n)
46 {
47   PetscFunctionBegin;
48   while (n--) *arg1++ = arg2;
49   PetscFunctionReturn(0);
50 }
51 
52 /***********************************ivec.c*************************************/
53 PetscErrorCode PCTFS_ivec_max(PetscInt *arg1, PetscInt *arg2, PetscInt n)
54 {
55   PetscFunctionBegin;
56   while (n--) { *arg1 = PetscMax(*arg1,*arg2); arg1++; arg2++; }
57   PetscFunctionReturn(0);
58 }
59 
60 /***********************************ivec.c*************************************/
61 PetscErrorCode PCTFS_ivec_min(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
62 {
63   PetscFunctionBegin;
64   while (n--) {
65     *(arg1) = PetscMin(*arg1,*arg2);
66     arg1++;
67     arg2++;
68   }
69   PetscFunctionReturn(0);
70 }
71 
72 /***********************************ivec.c*************************************/
73 PetscErrorCode PCTFS_ivec_mult(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
74 {
75   PetscFunctionBegin;
76   while (n--) *arg1++ *= *arg2++;
77   PetscFunctionReturn(0);
78 }
79 
80 /***********************************ivec.c*************************************/
81 PetscErrorCode PCTFS_ivec_add(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
82 {
83   PetscFunctionBegin;
84   while (n--) *arg1++ += *arg2++;
85   PetscFunctionReturn(0);
86 }
87 
88 /***********************************ivec.c*************************************/
89 PetscErrorCode PCTFS_ivec_lxor(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
90 {
91   PetscFunctionBegin;
92   while (n--) {
93     *arg1=((*arg1 || *arg2) && !(*arg1 && *arg2));
94     arg1++;
95     arg2++;
96   }
97   PetscFunctionReturn(0);
98 }
99 
100 /***********************************ivec.c*************************************/
101 PetscErrorCode PCTFS_ivec_xor(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
102 {
103   PetscFunctionBegin;
104   while (n--) *arg1++ ^= *arg2++;
105   PetscFunctionReturn(0);
106 }
107 
108 /***********************************ivec.c*************************************/
109 PetscErrorCode PCTFS_ivec_or(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
110 {
111   PetscFunctionBegin;
112   while (n--) *arg1++ |= *arg2++;
113   PetscFunctionReturn(0);
114 }
115 
116 /***********************************ivec.c*************************************/
117 PetscErrorCode PCTFS_ivec_lor(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
118 {
119   PetscFunctionBegin;
120   while (n--) {
121     *arg1 = (*arg1 || *arg2);
122     arg1++;
123     arg2++;
124   }
125   PetscFunctionReturn(0);
126 }
127 
128 /***********************************ivec.c*************************************/
129 PetscErrorCode PCTFS_ivec_and(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
130 {
131   PetscFunctionBegin;
132   while (n--) *arg1++ &= *arg2++;
133   PetscFunctionReturn(0);
134 }
135 
136 /***********************************ivec.c*************************************/
137 PetscErrorCode PCTFS_ivec_land(PetscInt *arg1,  PetscInt *arg2,  PetscInt n)
138 {
139   PetscFunctionBegin;
140   while (n--) {
141     *arg1 = (*arg1 && *arg2);
142     arg1++;
143     arg2++;
144   }
145   PetscFunctionReturn(0);
146 }
147 
148 /***********************************ivec.c*************************************/
149 PetscErrorCode PCTFS_ivec_and3(PetscInt *arg1,  PetscInt *arg2,  PetscInt *arg3, PetscInt n)
150 {
151   PetscFunctionBegin;
152   while (n--) *arg1++ = (*arg2++ & *arg3++);
153   PetscFunctionReturn(0);
154 }
155 
156 /***********************************ivec.c*************************************/
157 PetscInt PCTFS_ivec_sum(PetscInt *arg1,  PetscInt n)
158 {
159   PetscInt tmp = 0;
160   while (n--) tmp += *arg1++;
161   return(tmp);
162 }
163 
164 /***********************************ivec.c*************************************/
165 PetscErrorCode PCTFS_ivec_non_uniform(PetscInt *arg1, PetscInt *arg2,  PetscInt n,  PetscInt *arg3)
166 {
167   PetscInt i, j, type;
168 
169   PetscFunctionBegin;
170   /* LATER: if we're really motivated we can sort and then unsort */
171   for (i=0; i<n; ) {
172     /* clump 'em for now */
173     j    =i+1;
174     type = arg3[i];
175     while ((j<n)&&(arg3[j]==type)) j++;
176 
177     /* how many together */
178     j -= i;
179 
180     /* call appropriate ivec function */
181     if (type == GL_MAX)        PCTFS_ivec_max(arg1,arg2,j);
182     else if (type == GL_MIN)   PCTFS_ivec_min(arg1,arg2,j);
183     else if (type == GL_MULT)  PCTFS_ivec_mult(arg1,arg2,j);
184     else if (type == GL_ADD)   PCTFS_ivec_add(arg1,arg2,j);
185     else if (type == GL_B_XOR) PCTFS_ivec_xor(arg1,arg2,j);
186     else if (type == GL_B_OR)  PCTFS_ivec_or(arg1,arg2,j);
187     else if (type == GL_B_AND) PCTFS_ivec_and(arg1,arg2,j);
188     else if (type == GL_L_XOR) PCTFS_ivec_lxor(arg1,arg2,j);
189     else if (type == GL_L_OR)  PCTFS_ivec_lor(arg1,arg2,j);
190     else if (type == GL_L_AND) PCTFS_ivec_land(arg1,arg2,j);
191     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"unrecognized type passed to PCTFS_ivec_non_uniform()!");
192 
193     arg1+=j; arg2+=j; i+=j;
194   }
195   PetscFunctionReturn(0);
196 }
197 
198 /***********************************ivec.c*************************************/
199 vfp PCTFS_ivec_fct_addr(PetscInt type)
200 {
201   if (type == NON_UNIFORM)   return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_non_uniform);
202   else if (type == GL_MAX)   return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_max);
203   else if (type == GL_MIN)   return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_min);
204   else if (type == GL_MULT)  return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_mult);
205   else if (type == GL_ADD)   return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_add);
206   else if (type == GL_B_XOR) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_xor);
207   else if (type == GL_B_OR)  return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_or);
208   else if (type == GL_B_AND) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_and);
209   else if (type == GL_L_XOR) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_lxor);
210   else if (type == GL_L_OR)  return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_lor);
211   else if (type == GL_L_AND) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_ivec_land);
212 
213   /* catch all ... not good if we get here */
214   return(NULL);
215 }
216 
217 /******************************************************************************/
218 PetscErrorCode PCTFS_ivec_sort(PetscInt *ar,  PetscInt size)
219 {
220   PetscInt *pi, *pj, temp;
221   PetscInt **top_a = (PetscInt**) offset_stack;
222   PetscInt *top_s  = size_stack, *bottom_s = size_stack;
223 
224 
225   /* we're really interested in the offset of the last element */
226   /* ==> length of the list is now size + 1                    */
227   size--;
228 
229   /* do until we're done ... return when stack is exhausted */
230   for (;; ) {
231     /* if list is large enough use quicksort partition exchange code */
232     if (size > SORT_OPT) {
233       /* start up pointer at element 1 and down at size     */
234       pi = ar+1;
235       pj = ar+size;
236 
237       /* find middle element in list and swap w/ element 1 */
238       SWAP(*(ar+(size>>1)),*pi)
239 
240       /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
241       /* note ==> pivot_value in index 0                   */
242       if (*pi > *pj) { SWAP(*pi,*pj) }
243       if (*ar > *pj) { SWAP(*ar,*pj) }
244       else if (*pi > *ar) { SWAP(*(ar),*(ar+1)) }
245 
246       /* partition about pivot_value ...                              */
247       /* note lists of length 2 are not guaranteed to be sorted */
248       for (;; ) {
249         /* walk up ... and down ... swap if equal to pivot! */
250         do pi++; while (*pi<*ar);
251         do pj--; while (*pj>*ar);
252 
253         /* if we've crossed we're done */
254         if (pj<pi) break;
255 
256         /* else swap */
257         SWAP(*pi,*pj)
258       }
259 
260       /* place pivot_value in it's correct location */
261       SWAP(*ar,*pj)
262 
263       /* test stack_size to see if we've exhausted our stack */
264       if (top_s-bottom_s >= SORT_STACK) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PCTFS_ivec_sort() :: STACK EXHAUSTED!!!");
265 
266       /* push right hand child iff length > 1 */
267       if ((*top_s = size-((PetscInt) (pi-ar)))) {
268         *(top_a++) = pi;
269         size      -= *top_s+2;
270         top_s++;
271       } else if (size -= *top_s+2) ;   /* set up for next loop iff there is something to do */
272       else { /* might as well pop - note NR_OPT >=2 ==> we're ok! */
273         ar   = *(--top_a);
274         size = *(--top_s);
275       }
276     } else { /* else sort small list directly then pop another off stack */
277 
278       /* insertion sort for bottom */
279       for (pj=ar+1; pj<=ar+size; pj++) {
280         temp = *pj;
281         for (pi=pj-1; pi>=ar; pi--) {
282           if (*pi <= temp) break;
283           *(pi+1)=*pi;
284         }
285         *(pi+1)=temp;
286       }
287 
288       /* check to see if stack is exhausted ==> DONE */
289       if (top_s==bottom_s) PetscFunctionReturn(0);
290 
291       /* else pop another list from the stack */
292       ar   = *(--top_a);
293       size = *(--top_s);
294     }
295   }
296   PetscFunctionReturn(0);
297 }
298 
299 /******************************************************************************/
300 PetscErrorCode PCTFS_ivec_sort_companion(PetscInt *ar,  PetscInt *ar2,  PetscInt size)
301 {
302   PetscInt *pi, *pj, temp, temp2;
303   PetscInt **top_a = (PetscInt**)offset_stack;
304   PetscInt *top_s  = size_stack, *bottom_s = size_stack;
305   PetscInt *pi2, *pj2;
306   PetscInt mid;
307 
308   PetscFunctionBegin;
309   /* we're really interested in the offset of the last element */
310   /* ==> length of the list is now size + 1                    */
311   size--;
312 
313   /* do until we're done ... return when stack is exhausted */
314   for (;; ) {
315 
316     /* if list is large enough use quicksort partition exchange code */
317     if (size > SORT_OPT) {
318 
319       /* start up pointer at element 1 and down at size     */
320       mid = size>>1;
321       pi  = ar+1;
322       pj  = ar+mid;
323       pi2 = ar2+1;
324       pj2 = ar2+mid;
325 
326       /* find middle element in list and swap w/ element 1 */
327       SWAP(*pi,*pj)
328       SWAP(*pi2,*pj2)
329 
330       /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
331       /* note ==> pivot_value in index 0                   */
332       pj  = ar+size;
333       pj2 = ar2+size;
334       if (*pi > *pj) { SWAP(*pi,*pj) SWAP(*pi2,*pj2) }
335       if (*ar > *pj) { SWAP(*ar,*pj) SWAP(*ar2,*pj2) }
336       else if (*pi > *ar) { SWAP(*(ar),*(ar+1)) SWAP(*(ar2),*(ar2+1)) }
337 
338       /* partition about pivot_value ...                              */
339       /* note lists of length 2 are not guaranteed to be sorted */
340       for (;; ) {
341         /* walk up ... and down ... swap if equal to pivot! */
342         do { pi++; pi2++; } while (*pi<*ar);
343         do { pj--; pj2--; } while (*pj>*ar);
344 
345         /* if we've crossed we're done */
346         if (pj<pi) break;
347 
348         /* else swap */
349         SWAP(*pi,*pj)
350         SWAP(*pi2,*pj2)
351       }
352 
353       /* place pivot_value in it's correct location */
354       SWAP(*ar,*pj)
355       SWAP(*ar2,*pj2)
356 
357       /* test stack_size to see if we've exhausted our stack */
358       if (top_s-bottom_s >= SORT_STACK) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PCTFS_ivec_sort_companion() :: STACK EXHAUSTED!!!");
359 
360       /* push right hand child iff length > 1 */
361       if ((*top_s = size-((PetscInt) (pi-ar)))) {
362         *(top_a++) = pi;
363         *(top_a++) = pi2;
364         size      -= *top_s+2;
365         top_s++;
366       } else if (size -= *top_s+2) ;   /* set up for next loop iff there is something to do */
367       else {  /* might as well pop - note NR_OPT >=2 ==> we're ok! */
368         ar2  = *(--top_a);
369         ar   = *(--top_a);
370         size = *(--top_s);
371       }
372     } else { /* else sort small list directly then pop another off stack */
373 
374       /* insertion sort for bottom */
375       for (pj=ar+1, pj2=ar2+1; pj<=ar+size; pj++,pj2++) {
376         temp  = *pj;
377         temp2 = *pj2;
378         for (pi=pj-1,pi2=pj2-1; pi>=ar; pi--,pi2--) {
379           if (*pi <= temp) break;
380           *(pi+1) =*pi;
381           *(pi2+1)=*pi2;
382         }
383         *(pi+1) =temp;
384         *(pi2+1)=temp2;
385       }
386 
387       /* check to see if stack is exhausted ==> DONE */
388       if (top_s==bottom_s) PetscFunctionReturn(0);
389 
390       /* else pop another list from the stack */
391       ar2  = *(--top_a);
392       ar   = *(--top_a);
393       size = *(--top_s);
394     }
395   }
396   PetscFunctionReturn(0);
397 }
398 
399 /******************************************************************************/
400 PetscErrorCode PCTFS_ivec_sort_companion_hack(PetscInt *ar,  PetscInt **ar2, PetscInt size)
401 {
402   PetscInt *pi, *pj, temp, *ptr;
403   PetscInt **top_a = (PetscInt**)offset_stack;
404   PetscInt *top_s  = size_stack, *bottom_s = size_stack;
405   PetscInt **pi2, **pj2;
406   PetscInt mid;
407 
408   PetscFunctionBegin;
409   /* we're really interested in the offset of the last element */
410   /* ==> length of the list is now size + 1                    */
411   size--;
412 
413   /* do until we're done ... return when stack is exhausted */
414   for (;; ) {
415 
416     /* if list is large enough use quicksort partition exchange code */
417     if (size > SORT_OPT) {
418 
419       /* start up pointer at element 1 and down at size     */
420       mid = size>>1;
421       pi  = ar+1;
422       pj  = ar+mid;
423       pi2 = ar2+1;
424       pj2 = ar2+mid;
425 
426       /* find middle element in list and swap w/ element 1 */
427       SWAP(*pi,*pj)
428       P_SWAP(*pi2,*pj2)
429 
430       /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */
431       /* note ==> pivot_value in index 0                   */
432       pj  = ar+size;
433       pj2 = ar2+size;
434       if (*pi > *pj) { SWAP(*pi,*pj) P_SWAP(*pi2,*pj2) }
435       if (*ar > *pj) { SWAP(*ar,*pj) P_SWAP(*ar2,*pj2) }
436       else if (*pi > *ar) { SWAP(*(ar),*(ar+1)) P_SWAP(*(ar2),*(ar2+1)) }
437 
438       /* partition about pivot_value ...                              */
439       /* note lists of length 2 are not guaranteed to be sorted */
440       for (;; ) {
441 
442         /* walk up ... and down ... swap if equal to pivot! */
443         do {pi++; pi2++;} while (*pi<*ar);
444         do {pj--; pj2--;} while (*pj>*ar);
445 
446         /* if we've crossed we're done */
447         if (pj<pi) break;
448 
449         /* else swap */
450         SWAP(*pi,*pj)
451         P_SWAP(*pi2,*pj2)
452       }
453 
454       /* place pivot_value in it's correct location */
455       SWAP(*ar,*pj)
456       P_SWAP(*ar2,*pj2)
457 
458       /* test stack_size to see if we've exhausted our stack */
459       if (top_s-bottom_s >= SORT_STACK) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PCTFS_ivec_sort_companion_hack() :: STACK EXHAUSTED!!!");
460 
461       /* push right hand child iff length > 1 */
462       if ((*top_s = size-((PetscInt) (pi-ar)))) {
463         *(top_a++) = pi;
464         *(top_a++) = (PetscInt*) pi2;
465         size      -= *top_s+2;
466         top_s++;
467       } else if (size -= *top_s+2) ;   /* set up for next loop iff there is something to do */
468       else { /* might as well pop - note NR_OPT >=2 ==> we're ok! */
469         ar2  = (PetscInt**) *(--top_a);
470         ar   = *(--top_a);
471         size = *(--top_s);
472       }
473     } else  { /* else sort small list directly then pop another off stack */
474       /* insertion sort for bottom */
475       for (pj=ar+1, pj2=ar2+1; pj<=ar+size; pj++,pj2++) {
476         temp = *pj;
477         ptr  = *pj2;
478         for (pi=pj-1,pi2=pj2-1; pi>=ar; pi--,pi2--) {
479           if (*pi <= temp) break;
480           *(pi+1) =*pi;
481           *(pi2+1)=*pi2;
482         }
483         *(pi+1) =temp;
484         *(pi2+1)=ptr;
485       }
486 
487       /* check to see if stack is exhausted ==> DONE */
488       if (top_s==bottom_s) PetscFunctionReturn(0);
489 
490       /* else pop another list from the stack */
491       ar2  = (PetscInt**)*(--top_a);
492       ar   = *(--top_a);
493       size = *(--top_s);
494     }
495   }
496   PetscFunctionReturn(0);
497 }
498 
499 /******************************************************************************/
500 PetscErrorCode PCTFS_SMI_sort(void *ar1, void *ar2, PetscInt size, PetscInt type)
501 {
502   PetscFunctionBegin;
503   if (type == SORT_INTEGER) {
504     if (ar2) PCTFS_ivec_sort_companion((PetscInt*)ar1,(PetscInt*)ar2,size);
505     else PCTFS_ivec_sort((PetscInt*)ar1,size);
506   } else if (type == SORT_INT_PTR) {
507     if (ar2) PCTFS_ivec_sort_companion_hack((PetscInt*)ar1,(PetscInt**)ar2,size);
508     else PCTFS_ivec_sort((PetscInt*)ar1,size);
509   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PCTFS_SMI_sort only does SORT_INTEGER!");
510   PetscFunctionReturn(0);
511 }
512 
513 /***********************************ivec.c*************************************/
514 PetscInt PCTFS_ivec_linear_search(PetscInt item,  PetscInt *list,  PetscInt n)
515 {
516   PetscInt tmp = n-1;
517 
518   PetscFunctionBegin;
519   while (n--) {
520     if (*list++ == item) return(tmp-n);
521   }
522   return(-1);
523 }
524 
525 /***********************************ivec.c*************************************/
526 PetscInt PCTFS_ivec_binary_search(PetscInt item,  PetscInt *list,  PetscInt rh)
527 {
528   PetscInt mid, lh=0;
529 
530   rh--;
531   while (lh<=rh) {
532     mid = (lh+rh)>>1;
533     if (*(list+mid) == item) return(mid);
534     if (*(list+mid) > item) rh = mid-1;
535     else lh = mid+1;
536   }
537   return(-1);
538 }
539 
540 /*********************************ivec.c*************************************/
541 PetscErrorCode PCTFS_rvec_copy(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
542 {
543   PetscFunctionBegin;
544   while (n--) *arg1++ = *arg2++;
545   PetscFunctionReturn(0);
546 }
547 
548 /*********************************ivec.c*************************************/
549 PetscErrorCode PCTFS_rvec_zero(PetscScalar *arg1,  PetscInt n)
550 {
551   PetscFunctionBegin;
552   while (n--) *arg1++ = 0.0;
553   PetscFunctionReturn(0);
554 }
555 
556 /***********************************ivec.c*************************************/
557 PetscErrorCode PCTFS_rvec_one(PetscScalar *arg1,  PetscInt n)
558 {
559   PetscFunctionBegin;
560   while (n--) *arg1++ = 1.0;
561   PetscFunctionReturn(0);
562 }
563 
564 /***********************************ivec.c*************************************/
565 PetscErrorCode PCTFS_rvec_set(PetscScalar *arg1,  PetscScalar arg2,  PetscInt n)
566 {
567   PetscFunctionBegin;
568   while (n--) *arg1++ = arg2;
569   PetscFunctionReturn(0);
570 }
571 
572 /***********************************ivec.c*************************************/
573 PetscErrorCode PCTFS_rvec_scale(PetscScalar *arg1,  PetscScalar arg2,  PetscInt n)
574 {
575   PetscFunctionBegin;
576   while (n--) *arg1++ *= arg2;
577   PetscFunctionReturn(0);
578 }
579 
580 /*********************************ivec.c*************************************/
581 PetscErrorCode PCTFS_rvec_add(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
582 {
583   PetscFunctionBegin;
584   while (n--) *arg1++ += *arg2++;
585   PetscFunctionReturn(0);
586 }
587 
588 /*********************************ivec.c*************************************/
589 PetscErrorCode PCTFS_rvec_mult(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
590 {
591   PetscFunctionBegin;
592   while (n--) *arg1++ *= *arg2++;
593   PetscFunctionReturn(0);
594 }
595 
596 /*********************************ivec.c*************************************/
597 PetscErrorCode PCTFS_rvec_max(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
598 {
599   PetscFunctionBegin;
600   while (n--) {
601     *arg1 = PetscMax(*arg1,*arg2);
602     arg1++;
603     arg2++;
604   }
605   PetscFunctionReturn(0);
606 }
607 
608 /*********************************ivec.c*************************************/
609 PetscErrorCode PCTFS_rvec_max_abs(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
610 {
611   PetscFunctionBegin;
612   while (n--) {
613     *arg1 = MAX_FABS(*arg1,*arg2);
614     arg1++;
615     arg2++;
616   }
617   PetscFunctionReturn(0);
618 }
619 
620 /*********************************ivec.c*************************************/
621 PetscErrorCode PCTFS_rvec_min(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
622 {
623   PetscFunctionBegin;
624   while (n--) {
625     *arg1 = PetscMin(*arg1,*arg2);
626     arg1++;
627     arg2++;
628   }
629   PetscFunctionReturn(0);
630 }
631 
632 /*********************************ivec.c*************************************/
633 PetscErrorCode PCTFS_rvec_min_abs(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
634 {
635   PetscFunctionBegin;
636   while (n--) {
637     *arg1 = MIN_FABS(*arg1,*arg2);
638     arg1++;
639     arg2++;
640   }
641   PetscFunctionReturn(0);
642 }
643 
644 /*********************************ivec.c*************************************/
645 PetscErrorCode PCTFS_rvec_exists(PetscScalar *arg1,  PetscScalar *arg2,  PetscInt n)
646 {
647   PetscFunctionBegin;
648   while (n--) {
649     *arg1 = EXISTS(*arg1,*arg2);
650     arg1++;
651     arg2++;
652   }
653   PetscFunctionReturn(0);
654 }
655 
656 /***********************************ivec.c*************************************/
657 PetscErrorCode PCTFS_rvec_non_uniform(PetscScalar *arg1, PetscScalar *arg2,  PetscInt n,  PetscInt *arg3)
658 {
659   PetscInt i, j, type;
660 
661   PetscFunctionBegin;
662   /* LATER: if we're really motivated we can sort and then unsort */
663   for (i=0; i<n; ) {
664 
665     /* clump 'em for now */
666     j    =i+1;
667     type = arg3[i];
668     while ((j<n)&&(arg3[j]==type)) j++;
669 
670     /* how many together */
671     j -= i;
672 
673     /* call appropriate ivec function */
674     if (type == GL_MAX)          PCTFS_rvec_max(arg1,arg2,j);
675     else if (type == GL_MIN)     PCTFS_rvec_min(arg1,arg2,j);
676     else if (type == GL_MULT)    PCTFS_rvec_mult(arg1,arg2,j);
677     else if (type == GL_ADD)     PCTFS_rvec_add(arg1,arg2,j);
678     else if (type == GL_MAX_ABS) PCTFS_rvec_max_abs(arg1,arg2,j);
679     else if (type == GL_MIN_ABS) PCTFS_rvec_min_abs(arg1,arg2,j);
680     else if (type == GL_EXISTS)  PCTFS_rvec_exists(arg1,arg2,j);
681     else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"unrecognized type passed to PCTFS_rvec_non_uniform()!");
682 
683     arg1+=j; arg2+=j; i+=j;
684   }
685   PetscFunctionReturn(0);
686 }
687 
688 /***********************************ivec.c*************************************/
689 vfp PCTFS_rvec_fct_addr(PetscInt type)
690 {
691   if (type == NON_UNIFORM)     return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_non_uniform);
692   else if (type == GL_MAX)     return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_max);
693   else if (type == GL_MIN)     return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_min);
694   else if (type == GL_MULT)    return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_mult);
695   else if (type == GL_ADD)     return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_add);
696   else if (type == GL_MAX_ABS) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_max_abs);
697   else if (type == GL_MIN_ABS) return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_min_abs);
698   else if (type == GL_EXISTS)  return((PetscErrorCode (*)(void*, void*, PetscInt, ...))&PCTFS_rvec_exists);
699 
700   /* catch all ... not good if we get here */
701   return(NULL);
702 }
703 
704 
705 
706 
707 
708 
709