/* 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 #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_UPB(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 /* 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 hi = POINT_INDEX(RECTDOMAIN_MAX(x->domain), i); const jint s = POINT_INDEX(RECTDOMAIN_STRIDE(x->domain), i); if (PREDICT_FALSE(s > 1 && ((q - lo) % s) != 0)) { fprintf(stderr, "bounds checking error at %s:\n failed condition: ", where); PRINT_DOMAIN(x->domain, stderr); fprintf(stderr, ".contains("); PRINT_POINT(p, stderr); fprintf(stderr, ")\n array was allocated at %s\n", x->where); assert(("array index out of bounds", 0)); exit(-2); } else if (PREDICT_FALSE((q < lo) | (q > hi))) { fprintf(stderr, "bounds checking error at %s:\n failed condition: ", 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 array was allocated at %s\n", x->where); assert(("array index out of bounds", 0)); exit(-2); } if (PREDICT_FALSE(str != 1 && (qm % str) != 0)) assert(("internal error: bad array descriptor", 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 */ INLINE_MODIFIER jint #ifdef TI_ARRAY_H ti_conv #else #ifndef _CONCAT #define _CONCAT_HELPER(a,b) a ## b #define _CONCAT(a,b) _CONCAT_HELPER(a,b) #endif #define ti_convinl _CONCAT(ti_conv,inl) 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 INLINE_MODIFIER 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; } INLINE_MODIFIER 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 INLINE_MODIFIER 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