/* -*- c++ -*- vim:et:sw=4:ft=cpp */ #ifndef POINT_H #define POINT_H 1 /* Template of a pure class interface definition. It contains no method definitions, these are supposed to be provided by specialisation. */ template struct Point3I: public R { public: Point3I(); Point3I(const float x,const float y,const float z); Point3I(const Point3I &that); Point3I &operator =(const Point3I &that); float xGet() const; float yGet() const; float zGet() const; float xPut(const float x); float yPut(const float y); float zPut(const float z); Point3I &sub(const Point3I &that); float dot(const Point3I &that) const; float norm2() const; }; /* Representation class for an unaligned point without SSE acceleration. */ struct Point3C { protected: float x,y,z; Point3C ( register const float x, register const float y, register const float z ) : x(x), y(y), z(z) {} }; /* Definition of 'Point3I' methods. */ template<> inline Point3I::Point3I() : Point3C(0.0f,0.0f,0.0f) { } template<> inline Point3I::Point3I ( register const float x,register const float y,register const float z ) : Point3C(x,y,z) { } template<> inline Point3I::Point3I(register const Point3I &that) : Point3C(that.x,that.y,that.z) { } template<> inline float Point3I::xGet() const { return this->x; } template<> inline float Point3I::yGet() const { return this->y; } template<> inline float Point3I::zGet() const { return this->z; } template<> inline float Point3I::xPut(register const float x) { return this->x = x; } template<> inline float Point3I::yPut(register const float y) { return this->y = y; } template<> inline float Point3I::zPut(register const float z) { return this->z = z; } template<> inline Point3I &Point3I::operator = ( register const Point3I &that ) { this->x = that.x, this->y = that.y, this->z = that.z; return *this; } template<> inline Point3I &Point3I::sub ( register const Point3I &that ) { this->x -= that.x, this->y -= that.y, this->z -= that.z; return *this; } template<> inline float Point3I::dot(register const Point3I &that) const { return this->x*that.x + this->y*that.y + this->z*that.z; } template<> inline float Point3I::norm2() const { return this->dot(*this); } #if defined __SSE__ #include /* Representation class for an aligned point with SSE acceleration. */ struct Point3S { union { __m128 q; float v[4]; struct { float w,x,y,z; }; }; Point3S(register const __m128 q) : q(q) {} }; /* Definition of 'Point3I' methods, using SSE. */ template<> inline Point3I::Point3I() : Point3S(_mm_xor_ps(this->q,this->q)) { } template<> inline Point3I::Point3I ( register const float x,register const float y,register const float z ) : Point3S(_mm_set_ps(z,y,x,0.0f)) { } template<> inline Point3I::Point3I(register const Point3I &that) : Point3S(that.q) { } template<> inline float Point3I::xGet() const { return this->x; } template<> inline float Point3I::yGet() const { return this->y; } template<> inline float Point3I::zGet() const { return this->z; } template<> inline float Point3I::xPut(register const float x) { return this->x = x; } template<> inline float Point3I::yPut(register const float y) { return this->y = y; } template<> inline float Point3I::zPut(register const float z) { return this->z = z; } template<> inline Point3I &Point3I::operator = ( register const Point3I &that ) { this->q = that.q; return *this; } template<> inline Point3I &Point3I::sub ( register const Point3I &that ) { this->q = _mm_sub_ps(this->q,that.q); return *this; } /** * Add together the first 3 elements of the parameter, * and return the value as element 0 of the result. * * Horizontal adds are part of SSE2 but not SSE. */ static inline __m128 _mm_local_hadd_ps(register const __m128 q) { return _mm_add_ss( _mm_shuffle_ps(q,q,_MM_SHUFFLE(1,1,1,1)), _mm_add_ss( _mm_shuffle_ps(q,q,_MM_SHUFFLE(2,2,2,2)), _mm_shuffle_ps(q,q,_MM_SHUFFLE(3,3,3,3)))); } template<> inline float Point3I::dot(register const Point3I &that) const { register float d; _mm_store_ss(&d,_mm_local_hadd_ps(_mm_mul_ps(this->q,that.q))); return d; } template<> inline float Point3I::norm2() const { return this->dot(*this); } #endif #endif