/* this file included by both ti_array.h and ti_array.c - contains common code */ #if !defined(TI_ARRAY_H) && !defined(TI_ARRAY_C) #error this header should not be included directly #endif #ifndef _CONCAT #define _CONCAT_HELPER(a,b) a ## b #define _CONCAT(a,b) _CONCAT_HELPER(a,b) #endif #ifndef _IDENTITY #define _IDENTITY(x) (x) #endif #ifndef _STRINGIFY #define _STRINGIFY_HELPER(x) #x #define _STRINGIFY(x) _STRINGIFY_HELPER(x) #endif #define PRINT_POINT(p, f) \ do { \ jint _i; \ fprintf(f, "["); \ for (_i = 1; _i <= N; _i++) \ fprintf(f, (_i > 1) ? ", %d" : "%d", POINT_INDEX(p, _i)); \ fprintf(f, "]"); \ } while (0) #define PRINT_DOMAIN(R, f) \ do { \ jint _i; \ ti_POINT p = RECTDOMAIN_STRIDE(R); \ fputs("[", f); \ PRINT_POINT(RECTDOMAIN_MIN(R), f); \ fputs(" : ", f); \ PRINT_POINT(RECTDOMAIN_MAX(R), f); \ for (_i = 1; _i <= N; _i++) \ if (POINT_INDEX(p, _i) >= 2) break; \ if (_i <= N) { \ fputs(" : ", f); \ PRINT_POINT(p, f); \ } \ fputs("]", f); \ } while (0) #ifndef FAST_DIVIDE #define FAST_DIVIDE(a,b) ((b) == 1 ? (a) : (a)/(b) ) #define PFAST_DIVIDE(a,b) (PREDICT_TRUE((b) == 1) ? (a) : (a)/(b) ) #endif #ifndef UNINITIALIZED_CHECKING #if BOUNDS_CHECKING #define UNINITIALIZED_CHECKING 1 #endif #endif #if UNINITIALIZED_CHECKING #define assertExists(x, where) do { \ if_pf (LOCAL_PART((x).A) == NULL) { \ fprintf(stderr, "fatal error on processor %i:\n" \ "attempt to use uninitialized array at %s\n", \ MYPROC, where); \ fflush(stderr); \ abort(); \ } } while (0) #else #define assertExists(x, where) ((void)0) #endif TI_INLINE(ti_isnull) jboolean ti_isnull(ti_ARRAY x) { return (LOCAL_PART(x.A) == NULL); } TI_INLINE(ti_equals) jboolean ti_equals(ti_ARRAY x, ti_ARRAY y) { jboolean const xnull = (LOCAL_PART(x.A) == NULL); jboolean const ynull = (LOCAL_PART(y.A) == NULL); if (xnull) return ynull; else if (ynull) return 0; else { #if 0 fprintf(stderr, "fatal error on processor %i:\n" "attempted to compare two non-null grids\n", MYPROC); fflush(stderr); abort(); #else return EQUAL(x.A,y.A) && RECTDOMAIN_EQUAL(x.domain,y.domain); #endif } } TI_INLINE(ti_empty) ti_ARRAY ti_empty() { static ti_ARRAY x = { 0 }; return x; } /* used to report source line numbers when bounds checking enabled * disable this with nobcheck because it greatly inflates the string table */ #if BOUNDS_CHECKING #undef TI_ARRAY_PTR_LOC #define TI_ARRAY_PTR_LOC(where_litstr) \ " in " __TI_CURRENT_FUNCTION__ \ " at " __FILE__ ":" _STRINGIFY(__LINE__) \ " (" where_litstr ")" #else #ifndef TI_ARRAY_PTR_LOC #define TI_ARRAY_PTR_LOC(where_litstr) "" #endif #endif /* Address of arr[p] is: * desc.A + ((p[1] - desc.base[0]) / desc.stride[0]) * desc.sideFactors[0] * + ((p[2] - desc.base[1]) / desc.stride[1]) * desc.sideFactors[1] * + ... */ #if BOUNDS_CHECKING #ifdef TI_ARRAY_H extern jint ti_conv(const char *where, const ti_ARRAY *x, ti_POINT p); #else extern jint ti_conv(const char *where, const ti_ARRAY *x, ti_POINT p) { register jint sum = 0; #if N_LARGER_THAN_1 jint i; #else #define i 1 #endif assertExists(*x, where); #if N_LARGER_THAN_1 for (i = N; i >= 1; i--) #endif { const jint str = x->stride[i-1]; const jint q = POINT_INDEX(p, i); const jint qm = q - x->base[i-1]; register jint delta = qm * x->sideFactors[i-1]; /* bounds check */ const jint lo = POINT_INDEX(RECTDOMAIN_MIN(x->domain), i); const jint upb = POINT_INDEX(RECTDOMAIN_UPB(x->domain), i); const jint s = POINT_INDEX(RECTDOMAIN_STRIDE(x->domain), i); if (PREDICT_FALSE(s > 1 && ((q - lo) % s) != 0)) { fprintf(stderr, "Array bounds violation on processor %i\n" "bounds checking error at %s:\n failed condition: ", MYPROC, where); PRINT_DOMAIN(x->domain, stderr); fprintf(stderr, ".contains("); PRINT_POINT(p, stderr); fprintf(stderr, ")\n"); #if EXPLICITLY_STORE_ALLOCATION_SITE fprintf(stderr, " array was allocated at %s\n", x->where); #endif fflush(stderr); abort(); exit(-2); } else if (PREDICT_FALSE((q < lo) | (q >= upb))) { fprintf(stderr, "Array bounds violation on processor %i\n" "bounds checking error at %s:\n failed condition: ", MYPROC, where); PRINT_POINT(RECTDOMAIN_MIN(x->domain), stderr); fprintf(stderr, " <= "); PRINT_POINT(p, stderr); fprintf(stderr, " <= "); PRINT_POINT(RECTDOMAIN_MAX(x->domain), stderr); fprintf(stderr, "\n"); #if EXPLICITLY_STORE_ALLOCATION_SITE fprintf(stderr, " array was allocated at %s\n", x->where); #endif fflush(stderr); abort(); exit(-2); } assert(("internal error: bad array descriptor", x->stride[i-1] == 1 || (qm % x->stride[i-1]) == 0)); /* At this point, x->stride[i-1] should divide qm. Of course, we only know for sure if bounds checking is on. */ if (PREDICT_FALSE(str != 1)) delta /= str; /* only do the expensive divide when necessary */ sum += delta; } #if !N_LARGER_THAN_1 #undef i #endif #if 0 fprintf(stderr, "conv("); PRINT_POINT(p, stderr); fprintf(stderr, ") = %d\n", sum); #endif return sum; } #endif #ifdef TI_ARRAY_C #define ti_convinl ti_conv #endif #else /* !BOUNDS_CHECKING */ /* carefully optimized, non-bounds-checking version */ #ifdef TI_ARRAY_H TI_INLINE(ti_conv) jint ti_conv #else #define ti_convinl _CONCAT(ti_conv,inl) TI_INLINE(ti_convinl) jint ti_convinl #endif (const char *where, const ti_ARRAY *x, ti_POINT p) { assertExists(*x, where); #if N == 1 { register jint const delta0 = (POINT_INDEX(p, 1) - x->base[0])*x->sideFactors[0]; return PFAST_DIVIDE(delta0,x->stride[0]); } #elif N == 2 { register jint const delta0 = (POINT_INDEX(p, 1) - x->base[0])*x->sideFactors[0]; register jint const delta1 = (POINT_INDEX(p, 2) - x->base[1])*x->sideFactors[1]; return PFAST_DIVIDE(delta0,x->stride[0]) + PFAST_DIVIDE(delta1,x->stride[1]); } #elif N == 3 { register jint const delta0 = (POINT_INDEX(p, 1) - x->base[0])*x->sideFactors[0]; register jint const delta1 = (POINT_INDEX(p, 2) - x->base[1])*x->sideFactors[1]; register jint const delta2 = (POINT_INDEX(p, 3) - x->base[2])*x->sideFactors[2]; return PFAST_DIVIDE(delta0,x->stride[0]) + PFAST_DIVIDE(delta1,x->stride[1]) + PFAST_DIVIDE(delta2,x->stride[2]); } #else { jint i; register jint sum = 0; for (i = N; i >= 1; i--) { /* At this point, x->stride[i-1] should divide qm. Of course, we only know for sure if bounds checking is on. */ const jint str = x->stride[i-1]; const jint q = POINT_INDEX(p, i); const jint qm = q - x->base[i-1]; register jint delta = qm * x->sideFactors[i-1]; if (PREDICT_FALSE(str != 1)) delta /= str; /* only do the expensive divide when necessary */ sum += delta; } #if 0 fprintf(stderr, "conv("); PRINT_POINT(p, stderr); fprintf(stderr, ") = %d\n", sum); #endif return sum; } #endif } #ifdef TI_ARRAY_C /* need to ensure an external defn */ extern jint ti_conv(const char *where, const ti_ARRAY *x, ti_POINT p) { return ti_convinl(where,x,p); } #endif #endif /* BOUNDS_CHECKING */ #ifdef TI_ARRAY_H TI_INLINE(ti_ptr) PTR_TO_T ti_ptr(const char *where, const ti_ARRAY x, ti_POINT p) { PTR_TO_T result; INDEX(result, x.A, ti_conv(where, &x, p)); return result; } TI_INLINE(ti_read) T ti_read(const char *where, const ti_ARRAY x, ti_POINT p) { PTR_TO_T ptr = ti_ptr(where, x, p); T result; deref(result, ptr); return result; } #if assignable TI_INLINE(ti_write) void ti_write(const char *where, const ti_ARRAY x, ti_POINT p, T value) { PTR_TO_T ptr = ti_ptr(where, x, p); assign(ptr, value); } #endif #endif