/**********************************ivec.c************************************** Author: Henry M. Tufo III e-mail: hmt@cs.brown.edu snail-mail: Division of Applied Mathematics Brown University Providence, RI 02912 Last Modification: 6.21.97 ***********************************ivec.c*************************************/ #include <../src/ksp/pc/impls/tfs/tfs.h> /* sorting args ivec.c ivec.c ... */ #define SORT_OPT 6 #define SORT_STACK 50000 /* allocate an address and size stack for sorter(s) */ static void *offset_stack[2 * SORT_STACK]; static PetscInt size_stack[SORT_STACK]; /***********************************ivec.c*************************************/ PetscInt *PCTFS_ivec_copy(PetscInt *arg1, PetscInt *arg2, PetscInt n) { while (n--) *arg1++ = *arg2++; return arg1; } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_zero(PetscInt *arg1, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = 0; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_set(PetscInt *arg1, PetscInt arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = arg2; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_max(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = PetscMax(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_min(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *(arg1) = PetscMin(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_mult(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ *= *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_add(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ += *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_lxor(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = (*arg1 || *arg2) && !(*arg1 && *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_xor(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ ^= *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_or(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ |= *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_lor(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = (*arg1 || *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_and(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ &= *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_land(PetscInt *arg1, PetscInt *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = (*arg1 && *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_and3(PetscInt *arg1, PetscInt *arg2, PetscInt *arg3, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = (*arg2++ & *arg3++); PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscInt PCTFS_ivec_sum(PetscInt *arg1, PetscInt n) { PetscInt tmp = 0; while (n--) tmp += *arg1++; return tmp; } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_ivec_non_uniform(PetscInt *arg1, PetscInt *arg2, PetscInt n, ...) { PetscInt i, j, type; PetscInt *arg3; va_list ap; PetscFunctionBegin; va_start(ap, n); arg3 = va_arg(ap, PetscInt *); va_end(ap); /* LATER: if we're really motivated we can sort and then unsort */ for (i = 0; i < n;) { /* clump 'em for now */ j = i + 1; type = arg3[i]; while ((j < n) && (arg3[j] == type)) j++; /* how many together */ j -= i; /* call appropriate ivec function */ if (type == GL_MAX) PetscCall(PCTFS_ivec_max(arg1, arg2, j)); else if (type == GL_MIN) PetscCall(PCTFS_ivec_min(arg1, arg2, j)); else if (type == GL_MULT) PetscCall(PCTFS_ivec_mult(arg1, arg2, j)); else if (type == GL_ADD) PetscCall(PCTFS_ivec_add(arg1, arg2, j)); else if (type == GL_B_XOR) PetscCall(PCTFS_ivec_xor(arg1, arg2, j)); else if (type == GL_B_OR) PetscCall(PCTFS_ivec_or(arg1, arg2, j)); else if (type == GL_B_AND) PetscCall(PCTFS_ivec_and(arg1, arg2, j)); else if (type == GL_L_XOR) PetscCall(PCTFS_ivec_lxor(arg1, arg2, j)); else if (type == GL_L_OR) PetscCall(PCTFS_ivec_lor(arg1, arg2, j)); else if (type == GL_L_AND) PetscCall(PCTFS_ivec_land(arg1, arg2, j)); else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "unrecognized type passed to PCTFS_ivec_non_uniform()!"); arg1 += j; arg2 += j; i += j; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ vfp PCTFS_ivec_fct_addr(PetscInt type) { if (type == NON_UNIFORM) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_non_uniform; else if (type == GL_MAX) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_max; else if (type == GL_MIN) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_min; else if (type == GL_MULT) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_mult; else if (type == GL_ADD) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_add; else if (type == GL_B_XOR) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_xor; else if (type == GL_B_OR) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_or; else if (type == GL_B_AND) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_and; else if (type == GL_L_XOR) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_lxor; else if (type == GL_L_OR) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_lor; else if (type == GL_L_AND) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_ivec_land; /* catch all ... not good if we get here */ return NULL; } /******************************************************************************/ PetscErrorCode PCTFS_ivec_sort(PetscInt *ar, PetscInt size) { PetscInt *pi, *pj, temp; PetscInt **top_a = (PetscInt **)offset_stack; PetscInt *top_s = size_stack, *bottom_s = size_stack; PetscFunctionBegin; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ pi = ar + 1; pj = ar + size; /* find middle element in list and swap w/ element 1 */ SWAP(*(ar + (size >> 1)), *pi); /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ if (*pi > *pj) SWAP(*pi, *pj); if (*ar > *pj) SWAP(*ar, *pj); else if (*pi > *ar) SWAP(*(ar), *(ar + 1)); /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for (;;) { /* walk up ... and down ... swap if equal to pivot! */ do pi++; while (*pi < *ar); do pj--; while (*pj > *ar); /* if we've crossed we're done */ if (pj < pi) break; /* else swap */ SWAP(*pi, *pj); } /* place pivot_value in it's correct location */ SWAP(*ar, *pj); /* test stack_size to see if we've exhausted our stack */ PetscCheck(top_s - bottom_s < SORT_STACK, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_ivec_sort() :: STACK EXHAUSTED!!!"); /* push right hand child iff length > 1 */ if ((*top_s = size - ((PetscInt)(pi - ar)))) { *(top_a++) = pi; size -= *top_s + 2; top_s++; } else if (size -= *top_s + 2) ; /* set up for next loop iff there is something to do */ else { /* might as well pop - note NR_OPT >=2 ==> we're ok! */ ar = *(--top_a); size = *(--top_s); } } else { /* else sort small list directly then pop another off stack */ /* insertion sort for bottom */ for (pj = ar + 1; pj <= ar + size; pj++) { temp = *pj; for (pi = pj - 1; pi >= ar; pi--) { if (*pi <= temp) break; *(pi + 1) = *pi; } *(pi + 1) = temp; } /* check to see if stack is exhausted ==> DONE */ if (top_s == bottom_s) PetscFunctionReturn(PETSC_SUCCESS); /* else pop another list from the stack */ ar = *(--top_a); size = *(--top_s); } } } /******************************************************************************/ PetscErrorCode PCTFS_ivec_sort_companion(PetscInt *ar, PetscInt *ar2, PetscInt size) { PetscInt *pi, *pj, temp, temp2; PetscInt **top_a = (PetscInt **)offset_stack; PetscInt *top_s = size_stack, *bottom_s = size_stack; PetscInt *pi2, *pj2; PetscInt mid; PetscFunctionBegin; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ mid = size >> 1; pi = ar + 1; pj = ar + mid; pi2 = ar2 + 1; pj2 = ar2 + mid; /* find middle element in list and swap w/ element 1 */ SWAP(*pi, *pj); SWAP(*pi2, *pj2); /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ pj = ar + size; pj2 = ar2 + size; if (*pi > *pj) { SWAP(*pi, *pj); SWAP(*pi2, *pj2); } if (*ar > *pj) { SWAP(*ar, *pj); SWAP(*ar2, *pj2); } else if (*pi > *ar) { SWAP(*(ar), *(ar + 1)); SWAP(*(ar2), *(ar2 + 1)); } /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for (;;) { /* walk up ... and down ... swap if equal to pivot! */ do { pi++; pi2++; } while (*pi < *ar); do { pj--; pj2--; } while (*pj > *ar); /* if we've crossed we're done */ if (pj < pi) break; /* else swap */ SWAP(*pi, *pj); SWAP(*pi2, *pj2); } /* place pivot_value in it's correct location */ SWAP(*ar, *pj); SWAP(*ar2, *pj2); /* test stack_size to see if we've exhausted our stack */ PetscCheck(top_s - bottom_s < SORT_STACK, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_ivec_sort_companion() :: STACK EXHAUSTED!!!"); /* push right hand child iff length > 1 */ if ((*top_s = size - ((PetscInt)(pi - ar)))) { *(top_a++) = pi; *(top_a++) = pi2; size -= *top_s + 2; top_s++; } else if (size -= *top_s + 2) ; /* set up for next loop iff there is something to do */ else { /* might as well pop - note NR_OPT >=2 ==> we're ok! */ ar2 = *(--top_a); ar = *(--top_a); size = *(--top_s); } } else { /* else sort small list directly then pop another off stack */ /* insertion sort for bottom */ for (pj = ar + 1, pj2 = ar2 + 1; pj <= ar + size; pj++, pj2++) { temp = *pj; temp2 = *pj2; for (pi = pj - 1, pi2 = pj2 - 1; pi >= ar; pi--, pi2--) { if (*pi <= temp) break; *(pi + 1) = *pi; *(pi2 + 1) = *pi2; } *(pi + 1) = temp; *(pi2 + 1) = temp2; } /* check to see if stack is exhausted ==> DONE */ if (top_s == bottom_s) PetscFunctionReturn(PETSC_SUCCESS); /* else pop another list from the stack */ ar2 = *(--top_a); ar = *(--top_a); size = *(--top_s); } } } /******************************************************************************/ PetscErrorCode PCTFS_ivec_sort_companion_hack(PetscInt *ar, PetscInt **ar2, PetscInt size) { PetscInt *pi, *pj, temp, *ptr; PetscInt **top_a = (PetscInt **)offset_stack; PetscInt *top_s = size_stack, *bottom_s = size_stack; PetscInt **pi2, **pj2; PetscInt mid; PetscFunctionBegin; /* we're really interested in the offset of the last element */ /* ==> length of the list is now size + 1 */ size--; /* do until we're done ... return when stack is exhausted */ for (;;) { /* if list is large enough use quicksort partition exchange code */ if (size > SORT_OPT) { /* start up pointer at element 1 and down at size */ mid = size >> 1; pi = ar + 1; pj = ar + mid; pi2 = ar2 + 1; pj2 = ar2 + mid; /* find middle element in list and swap w/ element 1 */ SWAP(*pi, *pj); P_SWAP(*pi2, *pj2); /* order element 0,1,size-1 st {M,L,...,U} w/L<=M<=U */ /* note ==> pivot_value in index 0 */ pj = ar + size; pj2 = ar2 + size; if (*pi > *pj) { SWAP(*pi, *pj); P_SWAP(*pi2, *pj2); } if (*ar > *pj) { SWAP(*ar, *pj); P_SWAP(*ar2, *pj2); } else if (*pi > *ar) { SWAP(*(ar), *(ar + 1)); P_SWAP(*(ar2), *(ar2 + 1)); } /* partition about pivot_value ... */ /* note lists of length 2 are not guaranteed to be sorted */ for (;;) { /* walk up ... and down ... swap if equal to pivot! */ do { pi++; pi2++; } while (*pi < *ar); do { pj--; pj2--; } while (*pj > *ar); /* if we've crossed we're done */ if (pj < pi) break; /* else swap */ SWAP(*pi, *pj); P_SWAP(*pi2, *pj2); } /* place pivot_value in it's correct location */ SWAP(*ar, *pj); P_SWAP(*ar2, *pj2); /* test stack_size to see if we've exhausted our stack */ PetscCheck(top_s - bottom_s < SORT_STACK, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_ivec_sort_companion_hack() :: STACK EXHAUSTED!!!"); /* push right hand child iff length > 1 */ if ((*top_s = size - ((PetscInt)(pi - ar)))) { *(top_a++) = pi; *(top_a++) = (PetscInt *)pi2; size -= *top_s + 2; top_s++; } else if (size -= *top_s + 2) ; /* set up for next loop iff there is something to do */ else { /* might as well pop - note NR_OPT >=2 ==> we're ok! */ ar2 = (PetscInt **)*(--top_a); ar = *(--top_a); size = *(--top_s); } } else { /* else sort small list directly then pop another off stack */ /* insertion sort for bottom */ for (pj = ar + 1, pj2 = ar2 + 1; pj <= ar + size; pj++, pj2++) { temp = *pj; ptr = *pj2; for (pi = pj - 1, pi2 = pj2 - 1; pi >= ar; pi--, pi2--) { if (*pi <= temp) break; *(pi + 1) = *pi; *(pi2 + 1) = *pi2; } *(pi + 1) = temp; *(pi2 + 1) = ptr; } /* check to see if stack is exhausted ==> DONE */ if (top_s == bottom_s) PetscFunctionReturn(PETSC_SUCCESS); /* else pop another list from the stack */ ar2 = (PetscInt **)*(--top_a); ar = *(--top_a); size = *(--top_s); } } } /******************************************************************************/ PetscErrorCode PCTFS_SMI_sort(void *ar1, void *ar2, PetscInt size, PetscInt type) { PetscFunctionBegin; if (type == SORT_INTEGER) { if (ar2) PetscCall(PCTFS_ivec_sort_companion((PetscInt *)ar1, (PetscInt *)ar2, size)); else PetscCall(PCTFS_ivec_sort((PetscInt *)ar1, size)); } else if (type == SORT_INT_PTR) { if (ar2) PetscCall(PCTFS_ivec_sort_companion_hack((PetscInt *)ar1, (PetscInt **)ar2, size)); else PetscCall(PCTFS_ivec_sort((PetscInt *)ar1, size)); } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCTFS_SMI_sort only does SORT_INTEGER!"); PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscInt PCTFS_ivec_linear_search(PetscInt item, PetscInt *list, PetscInt n) { PetscInt tmp = n - 1; while (n--) { if (*list++ == item) return tmp - n; } return -1; } /***********************************ivec.c*************************************/ PetscInt PCTFS_ivec_binary_search(PetscInt item, PetscInt *list, PetscInt rh) { PetscInt mid, lh = 0; rh--; while (lh <= rh) { mid = (lh + rh) >> 1; if (*(list + mid) == item) return mid; if (*(list + mid) > item) rh = mid - 1; else lh = mid + 1; } return -1; } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_copy(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_zero(PetscScalar *arg1, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = 0.0; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_one(PetscScalar *arg1, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = 1.0; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_set(PetscScalar *arg1, PetscScalar arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ = arg2; PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_scale(PetscScalar *arg1, PetscScalar arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ *= arg2; PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_add(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ += *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_mult(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) *arg1++ *= *arg2++; PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_max(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = PetscMax(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_max_abs(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = MAX_FABS(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_min(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = PetscMin(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ PetscErrorCode PCTFS_rvec_min_abs(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = MIN_FABS(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /*********************************ivec.c*************************************/ static PetscErrorCode PCTFS_rvec_exists(PetscScalar *arg1, PetscScalar *arg2, PetscInt n) { PetscFunctionBegin; while (n--) { *arg1 = EXISTS(*arg1, *arg2); arg1++; arg2++; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ static PetscErrorCode PCTFS_rvec_non_uniform(PetscScalar *arg1, PetscScalar *arg2, PetscInt n, PetscInt *arg3) { PetscInt i, j, type; PetscFunctionBegin; /* LATER: if we're really motivated we can sort and then unsort */ for (i = 0; i < n;) { /* clump 'em for now */ j = i + 1; type = arg3[i]; while ((j < n) && (arg3[j] == type)) j++; /* how many together */ j -= i; /* call appropriate ivec function */ if (type == GL_MAX) PetscCall(PCTFS_rvec_max(arg1, arg2, j)); else if (type == GL_MIN) PetscCall(PCTFS_rvec_min(arg1, arg2, j)); else if (type == GL_MULT) PetscCall(PCTFS_rvec_mult(arg1, arg2, j)); else if (type == GL_ADD) PetscCall(PCTFS_rvec_add(arg1, arg2, j)); else if (type == GL_MAX_ABS) PetscCall(PCTFS_rvec_max_abs(arg1, arg2, j)); else if (type == GL_MIN_ABS) PetscCall(PCTFS_rvec_min_abs(arg1, arg2, j)); else if (type == GL_EXISTS) PetscCall(PCTFS_rvec_exists(arg1, arg2, j)); else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "unrecognized type passed to PCTFS_rvec_non_uniform()!"); arg1 += j; arg2 += j; i += j; } PetscFunctionReturn(PETSC_SUCCESS); } /***********************************ivec.c*************************************/ vfp PCTFS_rvec_fct_addr(PetscInt type) { if (type == NON_UNIFORM) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_non_uniform; else if (type == GL_MAX) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_max; else if (type == GL_MIN) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_min; else if (type == GL_MULT) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_mult; else if (type == GL_ADD) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_add; else if (type == GL_MAX_ABS) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_max_abs; else if (type == GL_MIN_ABS) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_min_abs; else if (type == GL_EXISTS) return (PetscErrorCode (*)(void *, void *, PetscInt, ...))&PCTFS_rvec_exists; /* catch all ... not good if we get here */ return NULL; }