#ifndef TRIPLETS_VEC_H_ #define TRIPLETS_VEC_H_ #include #include "util.h" #include "layout-ptr.h" using namespace layout_ptr; #define F_PI 3.1415926f /** 2D vector with layout support */ template struct vec2_flex { // necessary for layouting magic to work typedef T layfield_t; typedef laygroup_t group_t; // a provisional typedef, for struct-internal use only typedef vec2_flex vec2; // vector components union {T x; group_t dummy0;}; union {T y; group_t dummy1;}; // no need to construct for non-id layouts static hostdevice__ vec2 from(T x, T y) { vec2 a; a.x = x; a.y = y; return a; } static hostdevice__ vec2 from(T r) { return from(r, r); } // but a need to cast into id layout from non-id layout hostdevice__ operator vec2() const { return vec2::from(x, y); } // assignment operators; ordinary assignment must be overridden as well hostdevice__ vec2 operator= (const vec2 &a) { x = a.x; y = a.y; return (vec2)*this; } hostdevice__ vec2 operator+= (const vec2 &a) { x += a.x; y += a.y; return (vec2)*this; } hostdevice__ vec2 operator-= (const vec2 &a) { x -= a.x; y -= a.y; return (vec2)*this; } hostdevice__ vec2 operator*= (const vec2 &a) { x *= a.x; y *= a.y; return (vec2)*this; } hostdevice__ vec2 operator/= (const vec2 &a) { x /= a.x; y /= a.y; return (vec2)*this; } }; // struct vec2_flex // specialize layflex_t for vec2 to provide additional info template struct layflex_t > { typedef vec2_flex flex_t; }; typedef vec2_flex fvec2; // TODO: add alias for vec2 = vec2_flex when it's C++11 template struct vec3_flex { typedef T layfield_t; typedef laygroup_t group_t; typedef vec3_flex vec3; static hostdevice__ vec3 from(T x, T y, T z) { vec3 a; a.x = x; a.y = y; a.z = z; return a; } static hostdevice__ vec3 from(T r) { return from(r, r, r); } hostdevice__ operator vec3() const { return vec3::from(x, y, z); } hostdevice__ vec3 operator= (const vec3 &a) { x = a.x; y = a.y; z = a.z; return (vec3)*this; } hostdevice__ vec3 operator+= (const vec3 &a) { x += a.x; y += a.y; z += a.z; return (vec3)*this; } hostdevice__ vec3 operator-= (const vec3 &a) { x -= a.x; y -= a.y; z -= a.z; return (vec3)*this; } hostdevice__ vec3 operator*= (const vec3 &a) { x *= a.x; y *= a.y; z *= a.z; return (vec3)*this; } hostdevice__ vec3 operator/= (const vec3 &a) { x /= a.x; y /= a.y; z /= a.z; return (vec3)*this; } hostdevice__ vec2_flex xy() const { return vec2_flex::from(x, y); } // vector components //T x, y, z; union { T x; group_t dummy0;}; union { T y; group_t dummy1;}; union { T z; group_t dummy2;}; }; // class vec3 // specialize layflex_t for vec3 to provide additional info template struct layflex_t > { typedef vec3_flex flex_t; }; typedef vec3_flex fvec3; // vec2 methods template inline hostdevice__ vec2_flex operator+ (const vec2_flex &a, const vec2_flex &b) { return vec2_flex::from(a.x + b.x, a.y + b.y); } template inline hostdevice__ vec2_flex operator-(const vec2_flex &b) { return vec2_flex::from(-b.x, -b.y); } template inline hostdevice__ vec2_flex operator- (const vec2_flex &a, const vec2_flex &b) { return vec2_flex::from(a.x - b.x, a.y - b.y); } template inline hostdevice__ vec2_flex operator* (const vec2_flex &a, const vec2_flex &b) { return vec2_flex::from(a.x * b.x, a.y * b.y); } template inline hostdevice__ vec2_flex operator* (T a, const vec2_flex &b) { return vec2_flex::from(a * b.x, a * b.y); } template inline hostdevice__ vec2_flex operator* (const vec2_flex &a, T b) { return vec2_flex::from(a.x * b, a.y * b); } template inline hostdevice__ vec2_flex operator/ (const vec2_flex &a, const vec2_flex &b) { return vec2_flex::from(a.x / b.x, a.y / b.y); } template inline hostdevice__ vec2_flex operator/ (const vec2_flex &a, T b) { return vec2_flex::from(a.x / b, a.y / b); } template inline hostdevice__ T dot(const vec2_flex &a, const vec2_flex &b) { return a.x * b.x + a.y * b.y; } template inline hostdevice__ T cross(const vec2_flex &a, const vec2_flex &b) { return a.x * b.y - a.y * b.x; } template inline hostdevice__ T len2(const vec2_flex &a) { return dot(a, a); } template inline hostdevice__ T dist2(const vec2_flex &a, const vec2_flex &b) { return len2(a - b); } template inline hostdevice__ T len(const vec2_flex &a) { return sqrtf(len2(a)); } template inline hostdevice__ T dist(const vec2_flex &a, const vec2_flex &b) { return len(a - b); } template inline hostdevice__ T phi(const vec2_flex &a) { return atan2f(a.y, a.x); } template inline hostdevice__ T dphi(const vec2_flex &a, const vec2_flex &b) { float d = phi(a) - phi(b); if(d < -F_PI) d += 2 * F_PI; else if(d >= F_PI) d -= 2 * F_PI; return d; } // dphi // this function just returns a number whose sign is the same one as of dphi template inline hostdevice__ T dphi_same_sign (const vec2_flex &a, const vec2_flex &b) { return a.y * b.x - a.x * b.y; } // dphi_same_sign // vector orthogonal to the current one and of same length template inline hostdevice__ vec2_flex normal_to(const vec2_flex &a) { return vec2_flex::from(a.y, -a.x); } /** normalized vector */ template inline hostdevice__ vec2_flex normalized(const vec2_flex &a) { T invlen = 1 / len(a); return a * invlen; } // vec3 methods template inline hostdevice__ vec3_flex operator+ (const vec3_flex &a, const vec3_flex &b) { return vec3_flex::from(a.x + b.x, a.y + b.y, a.z + b.z); } template inline hostdevice__ vec3_flex operator-(const vec3_flex &b) { return vec3_flex::from(-b.x, -b.y, -b.z); } template inline hostdevice__ vec3_flex operator- (const vec3_flex &a, const vec3_flex &b) { return vec3_flex::from(a.x - b.x, a.y - b.y, a.z - b.z); } template inline hostdevice__ vec3_flex operator* (const vec3_flex &a, const vec3_flex &b) { return vec3_flex::from(a.x * b.x, a.y * b.y, a.z * b.z); } template inline hostdevice__ vec3_flex operator*(T a, const vec3_flex &b) { return vec3_flex::from(a * b.x, a * b.y, a * b.z); } template inline hostdevice__ vec3_flex operator*(const vec3_flex &a, T b) { return vec3_flex::from(a.x * b, a.y * b, a.z * b); } template inline hostdevice__ vec3_flex operator/ (const vec3_flex &a, const vec3_flex &b) { return vec3_flex::from(a.x / b.x, a.y / b.y, a.z / b.z); } template inline hostdevice__ vec3_flex operator/(const vec3_flex &a, T b) { return vec3_flex::from(a.x / b, a.y / b, a.z / b); } template inline hostdevice__ T dot(const vec3_flex &a, const vec3_flex &b) { return a.x * b.x + a.y * b.y + a.z * b.z; } template inline hostdevice__ vec3_flex cross (const vec3_flex &a, const vec3_flex &b) { return vec3_flex::from (a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } template inline hostdevice__ T len2(const vec3_flex &a) { return dot(a, a); } template inline hostdevice__ T dist2(const vec3_flex &a, const vec3_flex &b) { return len2(a - b); } template inline hostdevice__ T len(const vec3_flex &a) { return sqrtf(len2(a)); } template inline hostdevice__ T dist(const vec3_flex &a, const vec3_flex &b) { return len(a - b); } template inline hostdevice__ T phi(const vec3_flex &a) { return atan2f(a.y, a.x); } template inline hostdevice__ T dphi(const vec3_flex &a, const vec3_flex &b) { float d = phi(a) - phi(b); if(d < -F_PI) d += 2 * F_PI; else if(d >= F_PI) d -= 2 * F_PI; return d; } // dphi // this function returns the cosine of dphi between two vectors template inline hostdevice__ T cosdphi(const vec3_flex &a, const vec3_flex &b) { vec2_flex a1 = a.xy(), b1 = b.xy(); return dot(a1, b1) / sqrtf(len2(a1) * len2(b1)); } // dcosphi // this function just returns a number whose sign is the same one as of dphi template inline hostdevice__ T dphi_same_sign(const vec3_flex &a, const vec3_flex &b) { return a.y * b.x - a.x * b.y; } // dphi_same_sign #endif