/* Copyright (c) 2004, Kentaro A. Kurahone * All Rights Reserved. */ #include "Vector.h" #include #include #include #include /* #if defined(???) #define HAS_SSE #endif */ #if defined(__APPLE__) || defined(MACOSX) #include #include #include #include //#include #define HAS_ALTIVEC /* from http://home.san.rr.com/altivec/Pages/TipArchive.html */ #define vec_not(A) vec_nor(A,A) #define vec_nand(A,B) vec_not(vec_and(A,B)) #define vec_abs(A) vec_sel(A,vec_sub( vec_sub(A,A),A),vec_cmpgt(vec_sub(A,A),A)) #define vec_2sComp(x) vec_sub(vec_sub(x,x), x) /* #include #if defined(__VEC__) #define HAS_ALTIVEC #endif */ #endif Vector *Vector_new(void) { Vector *self = calloc(1, sizeof(Vector)); Vector_setSize_(self, 1); return self; } void Vector_free(Vector *self) { if (self->values) free(self->values); free(self); } Vector *Vector_clone(Vector *self) { Vector *c = Vector_new(); Vector_copy_(c, self); return c; } Vector *Vector_subarray_(Vector *self, size_t localStart, size_t length) { if (self->size <= localStart + length) { Vector *c = Vector_new(); Vector_setSize_(c, length); memcpy(c->values, self->values, length * sizeof(NUM_TYPE)); return c; } return NULL; } void Vector_copy_(Vector *self, Vector *other) { if (self->size != other->size) { Vector_setSize_(self, other->size); } /* doesn't seem to work #ifdef HAS_ALTIVEC vScopy(self->size, self->values, other->values); #else */ memcpy(self->values, other->values, self->size * sizeof(NUM_TYPE)); /* #endif */ } void Vector_copyData_length_(Vector *self, uint8_t *data, size_t length) { size_t size = ceil(((double)length) / ((double)sizeof(NUM_TYPE))); Vector_setSize_(self, size); /* #ifdef HAS_ALTIVEC vScopy(self->size, self->values, data); #else */ memcpy(self->values, data, size * sizeof(NUM_TYPE)); /* #endif */ } uint8_t *Vector_bytes(Vector *self) { return (uint8_t *)self->values; } int Vector_equals_(Vector *self, Vector *other) { return memcmp(self->values, other->values, self->size * sizeof(NUM_TYPE)) == 0; } size_t Vector_sizeInBytes(Vector *self) { return self->size * sizeof(NUM_TYPE); } size_t Vector_size(Vector *self) { return self->size; } void Vector_setSize_(Vector *self, size_t size) { if (self->size == size) { return; } /* calloc already gives 16 byte allignment #ifdef HAS_ALTIVEC size_t minSize = size > self->size ? self->size : size; NUM_TYPE *v = vec_malloc(newMemSize); memset(v, 0, newMemSize); memcpy(v, self->values, minSize); free(self->values); self->values = v; //self->values = vec_realloc(self->values, size * sizeof(NUM_TYPE)); #else */ if (size) { self->values = realloc(self->values, size * sizeof(NUM_TYPE)); } /* When passing in a size of zero to malloc/realloc (e.g., * deallocating), it's implementation defined whether the null * pointer is return or a sentinel object is (C99 7.20.3/1). Thus * if size is zero, self->values may now be null. Since this * chunk of code simply zeroes out any differing space, that's now * unnecessary, and would result in illegal pointer arithmetic on * a null pointer anyway. emf*/ if (self->values) { /* if new size if bigger, make the new elements zeros */ if (self->size < size) { memset(self->values + self->size, 0, (size - self->size) * sizeof(NUM_TYPE)); } } /*#endif*/ self->size = size; } NUM_TYPE Vector_at_(Vector *self, size_t i) { if (i < self->size) return *(self->values + i); return 0; } void Vector_at_put_(Vector *self, size_t i, NUM_TYPE v) { if (i >= self->size) { Vector_setSize_(self, i + 1); } self->values[i] = v; } void Vector_setXYZ(Vector *self, NUM_TYPE x, NUM_TYPE y, NUM_TYPE z) { if (2 >= self->size) { Vector_setSize_(self, 3); } self->values[0] = x; self->values[1] = y; self->values[2] = z; } void Vector_getXYZ(Vector *self, NUM_TYPE *x, NUM_TYPE *y, NUM_TYPE *z) { if (2 >= self->size) { Vector_setSize_(self, 3); } *x = self->values[0]; *y = self->values[1]; *z = self->values[2]; } /* ------------------------------------------------------------------------ */ void Vector_addScalar_(Vector *self, NUM_TYPE v) { size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { *d1 += v; d1 ++; n--; } } void Vector_subtractScalar_(Vector *self, NUM_TYPE v) { NUM_TYPE *d1 = self->values; //#ifdef HAS_ALTIVEC //vSgesub(1, self->size, d1, 'n', d2, 'n', d1) //#else { size_t n = self->size; while (n) { *d1 -= v; d1 ++; n--; } } //#endif } void Vector_multiplyScalar_andAddTo_(Vector *self, NUM_TYPE v, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; /* #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vSaxpyD(self->size, v, d1, d2); #else vSaxpy(self->size, v, d1, d2); #endif //#elif HAS_SSE #else */ { size_t n = self->size; while (n) { *d2 += v * (*d1); d1 ++; d2 ++; n--; } } /* #endif */ } void Vector_multiplyScalar_(Vector *self, NUM_TYPE v) { NUM_TYPE *d1 = self->values; #ifdef HAS_ALTIVEC //const int inc = 1; //SSCAL(&(self->size), &v, d1, &inc) #ifdef NUM_TYPE_IS_DOUBLE vsmulD(d1, 1, &v, d1, 1, self->size); #else vsmul(d1, 1, &v, d1, 1, self->size); #endif //#elif HAS_SSE #else { size_t n = self->size; while (n) { *d1 *= v; d1 ++; n--; } } #endif } void Vector_divideScalar_(Vector *self, NUM_TYPE v) { NUM_TYPE *d1 = self->values; { size_t n = self->size; while (n) { if(v) *d1 /= v; else *d1 = 0; d1 ++; n--; } } } void Vector_negate(Vector *self) { NUM_TYPE *d1 = self->values; { size_t n = self->size; while (n) { *d1 = -(*d1); d1 ++; n--; } } } /* ------------------------------------------------------------------------ */ NUM_TYPE Vector_sum(Vector *self) { NUM_TYPE total = 0; size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { total += *d1; d1 ++; n --; } return total; } int Vector_addArray_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; if (self->size < other->size) { Vector_setSize_(self, other->size); } #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vaddD(d1, 1, d2, 1, d1, 1, other->size); #else vadd(d1, 1, d2, 1, d1, 1, other->size); #endif //vaddfp(d1, 1, d2, 1, d1, 1, self->size); //#elif HAS_SSE #else { size_t n = other->size; while (n) { *d1 += *d2; d1 ++; d2++; n --; } } #endif return 0; } int Vector_addArray_at_(Vector *self, Vector *other, size_t index) { NUM_TYPE *d1 = self->values + index; NUM_TYPE *d2 = other->values; size_t length; if (self->size < index) { return 0; } if (self->size - index < other->size) { length = self->size - index; } else { length = other->size; } #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vaddD(d1, 1, d2, 1, d1, 1, length); #else vadd(d1, 1, d2, 1, d1, 1, length); #endif //vaddfp(d1, 1, d2, 1, d1, 1, self->size); //#elif HAS_SSE #else { size_t n = length; while (n) { *d1 += *d2; d1 ++; d2++; n --; } } #endif return 0; } int Vector_addArray_at_xscale_yscale_(Vector *self, Vector *other, long start, NUM_TYPE xscale, NUM_TYPE yscale) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; long length = self->size; NUM_TYPE invxscale = 1.0 / xscale; long i = start; if (i < 0) i = 0; while (i < length) { long j = (((NUM_TYPE)i - (NUM_TYPE)start) * invxscale); if (j > other->size) { return 0; } if (j > -1) { d1[i] += d2[j] * yscale; } i ++; } return 0; } int Vector_subtractArray_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; if (self->size < other->size) { Vector_setSize_(self, other->size); } #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vsubD(d2, 1, d1, 1, d1, 1, other->size); #else vsub(d2, 1, d1, 1, d1, 1, other->size); #endif //#elif HAS_SSE #else { size_t n = other->size; while (n) { *d1 -= *d2; d1 ++; d2++; n --; } } #endif return 0; } int Vector_multiplyArray_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; if (self->size < other->size) { Vector_setSize_(self, other->size); } #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vmulD(d1, 1, d2, 1, d1, 1, other->size); #else vmul(d1, 1, d2, 1, d1, 1, other->size); #endif //#elif HAS_SSE #else { size_t n = other->size; while (n) { *d1 *= *d2; d1 ++; d2++; n --; } } #endif return 0; } int Vector_divideArray_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; if (self->size < other->size) { Vector_setSize_(self, other->size); } { size_t n = other->size; while (n) { if (*d2) { *d1 /= *d2; } else { *d1 = 0; } d1 ++; d2++; n --; } } return 0; } NUM_TYPE Vector_dotProduct_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; NUM_TYPE result = 0; if (self->size != other->size) { printf("Error: Vector_dotProduct_() sizes not equal\n"); return -1; } #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE dotprD(d1, 1, d2, 1, &result, self->size); #else dotpr(d1, 1, d2, 1, &result, self->size); #endif //#elif HAS_SSE #else { size_t n = self->size; while (n) { result += (*d1) * (*d2); d1 ++; d2++; n --; } } #endif return result; } NUM_TYPE Vector_product(Vector *self) { NUM_TYPE *d1 = self->values; NUM_TYPE result = 1; size_t n; for (n = 0; n < self->size; n ++) { result *= d1[n]; } return result; } void Vector_square(Vector *self) { NUM_TYPE *d1 = self->values; #ifdef HAS_ALTIVEC #ifdef NUM_TYPE_IS_DOUBLE vsqD(d1, 1, d1, 1, self->size); #else vsq(d1, 1, d1, 1, self->size); #endif //#elif HAS_SSE #else { size_t n = self->size; while (n) { *d1 *= (*d1); d1 ++; n --; } } #endif } void Vector_normalize(Vector *self) { NUM_TYPE v1 = Vector_max(self); NUM_TYPE v2 = (NUM_TYPE)fabs((double)Vector_min(self)); NUM_TYPE v = v1 > v2 ? v1 : v2; if (!v) return; Vector_multiplyScalar_(self, 1.0/v); } void Vector_absolute(Vector *self) { NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vfabf(d1); #else */ { size_t n = self->size; while (n) { if (*d1 < 0) *d1 = -(*d1); d1 ++; n --; } } } void Vector_log(Vector *self) { NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vlogf(d1); #else */ { size_t n = self->size; while (n) { *d1 = (NUM_TYPE)log((double)(*d1)); d1 ++; n --; } } } void Vector_log10(Vector *self) { size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { *d1 = (NUM_TYPE)log10((double)(*d1)); d1 ++; n --; } } void Vector_pow(Vector *self, double p) { size_t n = self->size; NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vipowf(d1, p); #else */ while (n) { *d1 = (NUM_TYPE)pow((double)(*d1), p); d1 ++; n --; } } void Vector_random(Vector *self, float min, float max) { size_t n = self->size; NUM_TYPE *d1 = self->values; NUM_TYPE range = max - min; while (n) { *d1 = min + range * ((NUM_TYPE)rand())/((NUM_TYPE)RAND_MAX); d1 ++; n --; } } int Vector_ElementCmp(const void *a, const void *b) { return *((NUM_TYPE *)a) < *((NUM_TYPE *)b); } void Vector_sort(Vector *self) { if (!self->size) { return; } qsort(self->values, self->size, sizeof(NUM_TYPE), Vector_ElementCmp); } int Vector_ElementReverseCmp(const void *a, const void *b) { return *((NUM_TYPE *)a) > *((NUM_TYPE *)b); } void Vector_reverseSort(Vector *self) { if (!self->size) { return; } qsort(self->values, self->size, sizeof(NUM_TYPE), Vector_ElementReverseCmp); } /* ---------------------------------------------------------- */ NUM_TYPE Vector_min(Vector *self) { NUM_TYPE m; size_t n = self->size; NUM_TYPE *d1 = self->values; if (!d1) return 0; m = *d1; while (n) { if (*d1 < m) m = *d1; d1 ++; n --; } return m; } NUM_TYPE Vector_max(Vector *self) { NUM_TYPE m; size_t n = self->size; NUM_TYPE *d1 = self->values; if (!d1) return 0; m = *d1; while (n) { if (*d1 > m) m = *d1; d1 ++; n --; } return m; } NUM_TYPE Vector_mean(Vector *self) { NUM_TYPE total = 0; size_t n = self->size; NUM_TYPE *d1 = self->values; if (!d1) return 0; while (n) { total += (*d1); d1 ++; n --; } return total / ((NUM_TYPE)self->size); } NUM_TYPE Vector_meanSquare(Vector *self) { NUM_TYPE total = 0; size_t n = self->size; NUM_TYPE *d1 = self->values; if (!d1) return 0; while (n) { total += (*d1)*(*d1); d1 ++; n --; } return total / ((NUM_TYPE)self->size); } void Vector_setMin_(Vector *self, NUM_TYPE v) { size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { if (*d1 < v) *d1 = v; d1 ++; n --; } } void Vector_setMax_(Vector *self, NUM_TYPE v) { size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { if (*d1 > v) *d1 = v; d1 ++; n --; } } void Vector_set_(Vector *self, NUM_TYPE v) { size_t n = self->size; NUM_TYPE *d1 = self->values; while (n) { *d1 = v; d1 ++; n --; } } NUM_TYPE Vector_rootMeanSquare(Vector *self) { return sqrt(Vector_meanSquare(self)); } #define PI 3.14159265 void Vector_sin(Vector *self) { NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vsinf(d1); #else */ { size_t n = self->size; while (n) { *d1 = (NUM_TYPE)sin((double)*d1); d1 ++; n --; } } } void Vector_cos(Vector *self) { NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vcosf(d1); #else */ { size_t n = self->size; while (n) { *d1 = (NUM_TYPE)cos((double)*d1); d1 ++; n --; } } } void Vector_tan(Vector *self) { NUM_TYPE *d1 = self->values; /* #ifdef HAS_ALTIVEC vtanf(d1); #else */ { size_t n = self->size; while (n) { *d1 = (NUM_TYPE)tan((double)*d1); d1 ++; n --; } } } /* ----------------------------------------------------------- */ PointData *Vector_pointData(Vector *self) { return (PointData *)self->values; } int Vector_lessThanOrEqualTo_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; size_t n = self->size < other->size ? self->size : other->size; //if (n != other->size) return 0; while (n) { if (*d1 > *d2) return 0; d1 ++; d2 ++; n --; } return 1; } int Vector_greaterThanOrEqualTo_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; size_t n = self->size < other->size ? self->size : other->size; //if (n != other->size) return 0; while (n) { if (*d1 < *d2) return 0; d1 ++; d2 ++; n --; } return 1; } int Vector_lessThanOrEqualTo_minus_(Vector *self, Vector *v2, Vector *v3) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = v2->values; NUM_TYPE *d3 = v3->values; size_t n = self->size; n = n < v2->size ? n : v2->size; n = n < v3->size ? n : v3->size; while (n) { if (*d1 > *d2 - *d3) return 0; d1 ++; d2 ++; n --; } return 1; } int Vector_greaterThanOrEqualTo_minus_(Vector *self, Vector *v2, Vector *v3) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = v2->values; NUM_TYPE *d3 = v3->values; size_t n = self->size; n = n < v2->size ? n : v2->size; n = n < v3->size ? n : v3->size; while (n) { if (*d1 < *d2 - *d3) return 0; d1 ++; d2 ++; n --; } return 1; } int Vector_lessThanOrEqualToScalar_(Vector *self, NUM_TYPE v) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { if (*d1 > v) return 0; d1 ++; n --; } return 1; } int Vector_greaterThanOrEqualToScalar_(Vector *self, NUM_TYPE v) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { if (*d1 < v) return 0; d1 ++; n --; } return 1; } void Vector_crossProduct_(Vector *self, Vector *other) { PointData *p = (PointData *)self->values; PointData *p2 = (PointData *)other->values; NUM_TYPE a[3] = { p->x, p->y, p->z }; NUM_TYPE b[3] = { p2->x, p2->y, p2->z }; NUM_TYPE i = (a[1]*b[2]) - (a[2]*b[1]); NUM_TYPE j = (a[2]*b[0]) - (a[0]*b[2]); NUM_TYPE k = (a[0]*b[1]) - (a[1]*b[0]); (p->x) = i; (p->y) = j; (p->z) = k; } NUM_TYPE Vector_distanceTo_(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; size_t n = self->size; NUM_TYPE sum = 0; if (n != other->size) return 0; while (n) { NUM_TYPE d = (*d2 - *d1); sum += d * d; d1 ++; d2 ++; n --; } return (NUM_TYPE)sqrt((double)sum); } void Vector_ceil(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { *d1 = (NUM_TYPE)ceil((double)*d1); d1 ++; n --; } } void Vector_floor(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { *d1 = (NUM_TYPE)floor((double)*d1); d1 ++; n --; } } void Vector_print(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; printf("vector("); while (n) { printf("%f", *d1); if (n) { printf(", "); } d1 ++; n --; } printf(")"); } int Vector_Min(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; size_t n = self->size; if (n != other->size) return -1; while (n) { if (*d1 > *d2) { *d1 = *d2; } d1 ++; d2 ++; n --; } return 0; } int Vector_Max(Vector *self, Vector *other) { NUM_TYPE *d1 = self->values; NUM_TYPE *d2 = other->values; size_t n = self->size; if (n != other->size) return -1; while (n) { if (*d1 < *d2) { *d1 = *d2; } d1 ++; d2 ++; n --; } return 0; } void Vector_zero(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { *d1 = 0; d1 ++; n --; } } int Vector_isZero(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { if (*d1) { return 0; } d1 ++; n --; } return 1; } void Vector_sign(Vector *self) { NUM_TYPE *d1 = self->values; size_t n = self->size; while (n) { if (*d1 < 0) { *d1 = -1; } else if(*d1 > 0) { *d1 = 1; }; d1 ++; n --; } } void Vector_rangeFill(Vector *self) { NUM_TYPE *d1 = self->values; size_t i, max = self->size; for (i = 0; i < max; i ++) { *d1 = i; d1 ++; } } // vector rangeFill(vector(2, 2), 0) == vector(0, 1, 0, 1) // vector rangeFill(vector(2, 2), 1) == vector(0, 0, 1, 1) void Vector_rangeFillWithShapeVectorDim(Vector *self, Vector *shape, size_t d) { Vector_setSize_(self, Vector_product(shape)); { NUM_TYPE *d1 = self->values; size_t i, max = self->size; NUM_TYPE *s = shape->values; size_t *c = calloc(1, sizeof(size_t) * (shape->size + 1)); //size_t dim = 0; size_t j; if (d > shape->size - 1) return; for (i = 0; i < max; i ++) { d1[i] = c[d]; c[0] ++; //printf("c[0] = %i\n", (int)c[0]); //printf("s[0] = %i\n", (int)s[0]); for (j = 0; (j < shape->size) && (c[j] > s[j] - 1); j ++) { c[j] = 0; c[j + 1] ++; } } free(c); } } /* void Vector_bitCount(Vector *self) { typedef vector unsigned char vUInt8; vector unsigned char CountBits( vUInt8 v ) { vUInt8 tab1 = (vUInt8) (0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4); vUInt8 tab2 = vec_add(tab1, vec_splat_u8(1)); vUInt8 highBits = vec_sr(v, vec_splat_u8(5) ); return vec_add( vec_perm( tab1, tab2, v ), vec_perm( tab1, tab2, highBits ) ); } } */