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 | |
32 | __forceinline Vec2( ) {} |
33 | __forceinline explicit Vec2( const T& a ) : x(a), y(a) {} |
34 | __forceinline Vec2( const T& x, const T& y ) : x(x), y(y) {} |
35 | |
36 | __forceinline Vec2( const Vec2& other ) { x = other.x; y = other.y; } |
37 | __forceinline Vec2( const Vec2fa& other ); |
38 | |
39 | 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 | |
48 | __forceinline Vec2( ZeroTy ) : x(zero), y(zero) {} |
49 | __forceinline Vec2( OneTy ) : x(one), y(one) {} |
50 | __forceinline Vec2( PosInfTy ) : x(pos_inf), y(pos_inf) {} |
51 | __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); } |
68 | template<typename T> __forceinline Vec2<T> abs ( const Vec2<T>& a ) { return Vec2<T>(abs (a.x), abs (a.y)); } |
69 | template<typename T> __forceinline Vec2<T> rcp ( const Vec2<T>& a ) { return Vec2<T>(rcp (a.x), rcp (a.y)); } |
70 | template<typename T> __forceinline Vec2<T> rsqrt ( const Vec2<T>& a ) { return Vec2<T>(rsqrt(a.x), rsqrt(a.y)); } |
71 | template<typename T> __forceinline Vec2<T> sqrt ( const Vec2<T>& a ) { return Vec2<T>(sqrt (a.x), sqrt (a.y)); } |
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 | |
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)); } |
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 | |
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) ); } |
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) ); } |
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) ); } |
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 | |
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) ); } |
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) ); } |
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) ); } |
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 | |
121 | template<typename T> __forceinline T reduce_add( const Vec2<T>& a ) { return a.x + a.y; } |
122 | template<typename T> __forceinline T reduce_mul( const Vec2<T>& a ) { return a.x * a.y; } |
123 | template<typename T> __forceinline T reduce_min( const Vec2<T>& a ) { return min(a.x, a.y); } |
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 | |
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 | /// Euclidean Space Operators |
148 | //////////////////////////////////////////////////////////////////////////////// |
149 | |
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); } |
151 | template<typename T> __forceinline Vec2<T> cross ( const Vec2<T>& a ) { return Vec2<T>(-a.y,a.x); } |
152 | template<typename T> __forceinline T length ( const Vec2<T>& a ) { return sqrt(dot(a,a)); } |
153 | template<typename T> __forceinline Vec2<T> normalize( const Vec2<T>& a ) { return a*rsqrt(dot(a,a)); } |
154 | template<typename T> __forceinline T distance ( const Vec2<T>& a, const Vec2<T>& b ) { return length(a-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 | |
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 | |
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 | |
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 | |
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> |
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 | |
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__) || defined(__ARM_NEON) |
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 | { |
222 | template<> __forceinline Vec2<float>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} |
223 | |
224 | #if defined(__SSE__) || defined(__ARM_NEON) |
225 | template<> __forceinline Vec2<vfloat4>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} |
226 | #endif |
227 | |
228 | #if defined(__AVX__) |
229 | template<> __forceinline Vec2<vfloat8>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} |
230 | #endif |
231 | |
232 | #if defined(__AVX512F__) |
233 | template<> __forceinline Vec2<vfloat16>::Vec2(const Vec2fa& a) : x(a.x), y(a.y) {} |
234 | #endif |
235 | } |
236 | |