1 // Copyright 2009-2021 Intel Corporation 2 // SPDX-License-Identifier: Apache-2.0 3 4 #pragma once 5 6 #include "math.h" 7 8 namespace embree 9 { 10 struct Vec2fa; 11 12 //////////////////////////////////////////////////////////////////////////////// 13 /// Generic 2D vector Class 14 //////////////////////////////////////////////////////////////////////////////// 15 16 template<typename T> struct Vec2 17 { 18 enum { N = 2 }; 19 union { 20 struct { T x, y; }; 21 #if !(defined(__WIN32__) && _MSC_VER == 1800) // workaround for older VS 2013 compiler 22 T components[N]; 23 #endif 24 }; 25 26 typedef T Scalar; 27 28 //////////////////////////////////////////////////////////////////////////////// 29 /// Construction 30 //////////////////////////////////////////////////////////////////////////////// 31 Vec2Vec232 __forceinline Vec2( ) {} Vec2Vec233 __forceinline explicit Vec2( const T& a ) : x(a), y(a) {} Vec2Vec234 __forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {} 35 Vec2Vec236 __forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; } 37 __forceinline Vec2( const Vec2fa& other ); 38 Vec2Vec239 template<typename T1> __forceinline Vec2( const Vec2<T1>& a ) : x(T(a.x)), y(T(a.y)) {} 40 template<typename T1> __forceinline Vec2& operator =( const Vec2<T1>& other ) { x = other.x; y = other.y; return *this; } 41 42 __forceinline Vec2& operator =( const Vec2& other ) { x = other.x; y = other.y; return *this; } 43 44 //////////////////////////////////////////////////////////////////////////////// 45 /// Constants 46 //////////////////////////////////////////////////////////////////////////////// 47 Vec2Vec248 __forceinline Vec2( ZeroTy ) : x(zero), y(zero) {} Vec2Vec249 __forceinline Vec2( OneTy ) : x(one), y(one) {} Vec2Vec250 __forceinline Vec2( PosInfTy ) : x(pos_inf), y(pos_inf) {} Vec2Vec251 __forceinline Vec2( NegInfTy ) : x(neg_inf), y(neg_inf) {} 52 53 #if defined(__WIN32__) && _MSC_VER == 1800 // workaround for older VS 2013 compiler 54 __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return (&x)[axis]; } 55 __forceinline T& operator [](const size_t axis) { assert(axis < 2); return (&x)[axis]; } 56 #else 57 __forceinline const T& operator [](const size_t axis) const { assert(axis < 2); return components[axis]; } 58 __forceinline T& operator [](const size_t axis ) { assert(axis < 2); return components[axis]; } 59 #endif 60 }; 61 62 //////////////////////////////////////////////////////////////////////////////// 63 /// Unary Operators 64 //////////////////////////////////////////////////////////////////////////////// 65 66 template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a ) { return Vec2<T>(+a.x, +a.y); } 67 template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a ) { return Vec2<T>(-a.x, -a.y); } abs(const Vec2<T> & a)68 template<typename T> __forceinline Vec2<T> abs ( const Vec2<T>& a ) { return Vec2<T>(abs (a.x), abs (a.y)); } rcp(const Vec2<T> & a)69 template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); } rsqrt(const Vec2<T> & a)70 template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); } sqrt(const Vec2<T> & a)71 template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); } frac(const Vec2<T> & a)72 template<typename T> __forceinline Vec2<T> frac ( const Vec2<T>& a ) { return Vec2<T>(frac (a.x), frac (a.y)); } 73 74 //////////////////////////////////////////////////////////////////////////////// 75 /// Binary Operators 76 //////////////////////////////////////////////////////////////////////////////// 77 78 template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x + b.x, a.y + b.y); } 79 template<typename T> __forceinline Vec2<T> operator +( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x + b , a.y + b ); } 80 template<typename T> __forceinline Vec2<T> operator +( const T& a, const Vec2<T>& b ) { return Vec2<T>(a + b.x, a + b.y); } 81 template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x - b.x, a.y - b.y); } 82 template<typename T> __forceinline Vec2<T> operator -( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x - b , a.y - b ); } 83 template<typename T> __forceinline Vec2<T> operator -( const T& a, const Vec2<T>& b ) { return Vec2<T>(a - b.x, a - b.y); } 84 template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x * b.x, a.y * b.y); } 85 template<typename T> __forceinline Vec2<T> operator *( const T& a, const Vec2<T>& b ) { return Vec2<T>(a * b.x, a * b.y); } 86 template<typename T> __forceinline Vec2<T> operator *( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x * b , a.y * b ); } 87 template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const Vec2<T>& b ) { return Vec2<T>(a.x / b.x, a.y / b.y); } 88 template<typename T> __forceinline Vec2<T> operator /( const Vec2<T>& a, const T& b ) { return Vec2<T>(a.x / b , a.y / b ); } 89 template<typename T> __forceinline Vec2<T> operator /( const T& a, const Vec2<T>& b ) { return Vec2<T>(a / b.x, a / b.y); } 90 min(const Vec2<T> & a,const Vec2<T> & b)91 template<typename T> __forceinline Vec2<T> min(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(min(a.x, b.x), min(a.y, b.y)); } max(const Vec2<T> & a,const Vec2<T> & b)92 template<typename T> __forceinline Vec2<T> max(const Vec2<T>& a, const Vec2<T>& b) { return Vec2<T>(max(a.x, b.x), max(a.y, b.y)); } 93 94 //////////////////////////////////////////////////////////////////////////////// 95 /// Ternary Operators 96 //////////////////////////////////////////////////////////////////////////////// 97 madd(const Vec2<T> & a,const Vec2<T> & b,const Vec2<T> & c)98 template<typename T> __forceinline Vec2<T> madd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a.x,b.x,c.x), madd(a.y,b.y,c.y) ); } msub(const Vec2<T> & a,const Vec2<T> & b,const Vec2<T> & c)99 template<typename T> __forceinline Vec2<T> msub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a.x,b.x,c.x), msub(a.y,b.y,c.y) ); } nmadd(const Vec2<T> & a,const Vec2<T> & b,const Vec2<T> & c)100 template<typename T> __forceinline Vec2<T> nmadd ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a.x,b.x,c.x),nmadd(a.y,b.y,c.y) ); } nmsub(const Vec2<T> & a,const Vec2<T> & b,const Vec2<T> & c)101 template<typename T> __forceinline Vec2<T> nmsub ( const Vec2<T>& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a.x,b.x,c.x),nmsub(a.y,b.y,c.y) ); } 102 madd(const T & a,const Vec2<T> & b,const Vec2<T> & c)103 template<typename T> __forceinline Vec2<T> madd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( madd(a,b.x,c.x), madd(a,b.y,c.y) ); } msub(const T & a,const Vec2<T> & b,const Vec2<T> & c)104 template<typename T> __forceinline Vec2<T> msub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>( msub(a,b.x,c.x), msub(a,b.y,c.y) ); } nmadd(const T & a,const Vec2<T> & b,const Vec2<T> & c)105 template<typename T> __forceinline Vec2<T> nmadd ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmadd(a,b.x,c.x),nmadd(a,b.y,c.y) ); } nmsub(const T & a,const Vec2<T> & b,const Vec2<T> & c)106 template<typename T> __forceinline Vec2<T> nmsub ( const T& a, const Vec2<T>& b, const Vec2<T>& c) { return Vec2<T>(nmsub(a,b.x,c.x),nmsub(a,b.y,c.y) ); } 107 108 //////////////////////////////////////////////////////////////////////////////// 109 /// Assignment Operators 110 //////////////////////////////////////////////////////////////////////////////// 111 112 template<typename T> __forceinline Vec2<T>& operator +=( Vec2<T>& a, const Vec2<T>& b ) { a.x += b.x; a.y += b.y; return a; } 113 template<typename T> __forceinline Vec2<T>& operator -=( Vec2<T>& a, const Vec2<T>& b ) { a.x -= b.x; a.y -= b.y; return a; } 114 template<typename T> __forceinline Vec2<T>& operator *=( Vec2<T>& a, const T& b ) { a.x *= b ; a.y *= b ; return a; } 115 template<typename T> __forceinline Vec2<T>& operator /=( Vec2<T>& a, const T& b ) { a.x /= b ; a.y /= b ; return a; } 116 117 //////////////////////////////////////////////////////////////////////////////// 118 /// Reduction Operators 119 //////////////////////////////////////////////////////////////////////////////// 120 reduce_add(const Vec2<T> & a)121 template<typename T> __forceinline T reduce_add( const Vec2<T>& a ) { return a.x + a.y; } reduce_mul(const Vec2<T> & a)122 template<typename T> __forceinline T reduce_mul( const Vec2<T>& a ) { return a.x * a.y; } reduce_min(const Vec2<T> & a)123 template<typename T> __forceinline T reduce_min( const Vec2<T>& a ) { return min(a.x, a.y); } reduce_max(const Vec2<T> & a)124 template<typename T> __forceinline T reduce_max( const Vec2<T>& a ) { return max(a.x, a.y); } 125 126 //////////////////////////////////////////////////////////////////////////////// 127 /// Comparison Operators 128 //////////////////////////////////////////////////////////////////////////////// 129 130 template<typename T> __forceinline bool operator ==( const Vec2<T>& a, const Vec2<T>& b ) { return a.x == b.x && a.y == b.y; } 131 template<typename T> __forceinline bool operator !=( const Vec2<T>& a, const Vec2<T>& b ) { return a.x != b.x || a.y != b.y; } 132 template<typename T> __forceinline bool operator < ( const Vec2<T>& a, const Vec2<T>& b ) { 133 if (a.x != b.x) return a.x < b.x; 134 if (a.y != b.y) return a.y < b.y; 135 return false; 136 } 137 138 //////////////////////////////////////////////////////////////////////////////// 139 /// Shift Operators 140 //////////////////////////////////////////////////////////////////////////////// 141 shift_right_1(const Vec2<T> & a)142 template<typename T> __forceinline Vec2<T> shift_right_1( const Vec2<T>& a ) { 143 return Vec2<T>(shift_right_1(a.x),shift_right_1(a.y)); 144 } 145 146 //////////////////////////////////////////////////////////////////////////////// 147 /// Euclidian Space Operators 148 //////////////////////////////////////////////////////////////////////////////// 149 dot(const Vec2<T> & a,const Vec2<T> & b)150 template<typename T> __forceinline T dot ( const Vec2<T>& a, const Vec2<T>& b ) { return madd(a.x,b.x,a.y*b.y); } cross(const Vec2<T> & a)151 template<typename T> __forceinline Vec2<T> cross ( const Vec2<T>& a ) { return Vec2<T>(-a.y,a.x); } length(const Vec2<T> & a)152 template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); } normalize(const Vec2<T> & a)153 template<typename T> __forceinline Vec2<T> normalize( const Vec2<T>& a ) { return a*rsqrt(dot(a,a)); } distance(const Vec2<T> & a,const Vec2<T> & b)154 template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-b); } det(const Vec2<T> & a,const Vec2<T> & b)155 template<typename T> __forceinline T det ( const Vec2<T>& a, const Vec2<T>& b ) { return a.x*b.y - a.y*b.x; } 156 normalize_safe(const Vec2<T> & a)157 template<typename T> __forceinline Vec2<T> normalize_safe( const Vec2<T>& a ) { 158 const T d = dot(a,a); return select(d == T( zero ),a, a*rsqrt(d) ); 159 } 160 161 //////////////////////////////////////////////////////////////////////////////// 162 /// Select 163 //////////////////////////////////////////////////////////////////////////////// 164 select(bool s,const Vec2<T> & t,const Vec2<T> & f)165 template<typename T> __forceinline Vec2<T> select ( bool s, const Vec2<T>& t, const Vec2<T>& f ) { 166 return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y)); 167 } 168 select(const Vec2<bool> & s,const Vec2<T> & t,const Vec2<T> & f)169 template<typename T> __forceinline Vec2<T> select ( const Vec2<bool>& s, const Vec2<T>& t, const Vec2<T>& f ) { 170 return Vec2<T>(select(s.x,t.x,f.x),select(s.y,t.y,f.y)); 171 } 172 select(const typename T::Bool & s,const Vec2<T> & t,const Vec2<T> & f)173 template<typename T> __forceinline Vec2<T> select ( const typename T::Bool& s, const Vec2<T>& t, const Vec2<T>& f ) { 174 return Vec2<T>(select(s,t.x,f.x),select(s,t.y,f.y)); 175 } 176 177 template<typename T> lerp(const Vec2<T> & v0,const Vec2<T> & v1,const T & t)178 __forceinline Vec2<T> lerp(const Vec2<T>& v0, const Vec2<T>& v1, const T& t) { 179 return madd(Vec2<T>(T(1.0f)-t),v0,t*v1); 180 } 181 maxDim(const Vec2<T> & a)182 template<typename T> __forceinline int maxDim ( const Vec2<T>& a ) 183 { 184 const Vec2<T> b = abs(a); 185 if (b.x > b.y) return 0; 186 else return 1; 187 } 188 189 //////////////////////////////////////////////////////////////////////////////// 190 /// Output Operators 191 //////////////////////////////////////////////////////////////////////////////// 192 193 template<typename T> __forceinline embree_ostream operator<<(embree_ostream cout, const Vec2<T>& a) { 194 return cout << "(" << a.x << ", " << a.y << ")"; 195 } 196 197 //////////////////////////////////////////////////////////////////////////////// 198 /// Default template instantiations 199 //////////////////////////////////////////////////////////////////////////////// 200 201 typedef Vec2<bool > Vec2b; 202 typedef Vec2<int > Vec2i; 203 typedef Vec2<float> Vec2f; 204 } 205 206 #include "vec2fa.h" 207 208 #if defined __SSE__ 209 #include "../simd/sse.h" 210 #endif 211 212 #if defined __AVX__ 213 #include "../simd/avx.h" 214 #endif 215 216 #if defined(__AVX512F__) 217 #include "../simd/avx512.h" 218 #endif 219 220 namespace embree 221 { Vec2(const Vec2fa & a)222 template<> __forceinline Vec2<float>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} 223 224 #if defined(__SSE__) Vec2(const Vec2fa & a)225 template<> __forceinline Vec2<vfloat4>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} 226 #endif 227 228 #if defined(__AVX__) Vec2(const Vec2fa & a)229 template<> __forceinline Vec2<vfloat8>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} 230 #endif 231 232 #if defined(__AVX512F__) Vec2(const Vec2fa & a)233 template<> __forceinline Vec2<vfloat16>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} 234 #endif 235 } 236