SeExpr

Vec.h
Go to the documentation of this file.
1 /*
2 Copyright Disney Enterprises, Inc. All rights reserved.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License
6 and the following modification to it: Section 6 Trademarks.
7 deleted and replaced with:
8
9 6. Trademarks. This License does not grant permission to use the
10 trade names, trademarks, service marks, or product names of the
11 Licensor and its affiliates, except as required for reproducing
12 the content of the NOTICE file.
13
14 You may obtain a copy of the License at
15 http://www.apache.org/licenses/LICENSE-2.0
16 */
17 #ifndef _vectest2_h_
18 #define _vectest2_h_
19 #include <iosfwd>
20 #include <cstdlib>
21 #include <cmath>
22 #include <iostream>
23 #include "Platform.h"
24
25 // To fix differences in template TYPENAME resolution between MSVC and other compilers
26 #if defined(WINDOWS)
27 # define TYPENAME
28 #else
29 # define TYPENAME typename
30 #endif
31
32 //#############################################################################
33 // Template Metaprogramming Helpers
34 namespace SeExpr2 {
36 template <bool b, class T>
37 struct seexpr_static_assert {};
39 template <class T>
40 struct seexpr_static_assert<true, T> {
41 typedef T TYPE;
42 };
43
45 template <bool c, class T = void>
46 struct my_enable_if {
47 typedef T TYPE;
48 };
50 template <class T>
51 struct my_enable_if<false, T> {
52 #if defined(WINDOWS)
53 typedef void TYPE;
54 #endif
55 };
56
58 template <bool c, class T1, class T2>
59 struct static_if {
60 typedef T1 TYPE;
61 };
63 template <class T1, class T2>
64 struct static_if<false, T1, T2> {
65 typedef T2 TYPE;
66 };
67
68 //#############################################################################
69 // Reduction class (helps prevent linear data dependency on reduce unroll)
70 template <class T, int d>
71 struct Reducer {
72 static T sum(T* data) {
73 T sum = 0;
74 for (int k = 0; k < d; k++) sum += data[k];
75 return sum;
76 }
77 };
78 template <class T>
79 struct Reducer<T, 1> {
80 static T sum(T* data) { return data[0]; }
81 };
82 template <class T>
83 struct Reducer<T, 2> {
84 static T sum(T* data) { return data[0] + data[1]; }
85 };
86 template <class T>
87 struct Reducer<T, 3> {
88 static T sum(T* data) { return data[0] + data[1] + data[2]; }
89 };
90 template <class T>
91 struct Reducer<T, 4> {
92 static T sum(T* data) { return (data[0] + data[1]) + (data[2] + data[3]); }
93 };
94
97 template <class T, int d, bool ref = false>
98 class Vec {
99 // static error types
100 struct INVALID_WITH_VECTOR_VALUE {};
101 struct INVALID_WITH_VECTOR_REFERENCE {};
102 struct INVALID_WITH_DIMENSION {};
103
105 typename static_if<ref, T*, T[d]>::TYPE x;
106
107 public:
108 typedef Vec<T, d, false> T_VEC_VALUE;
109 typedef Vec<T, d, true> T_VEC_REF;
110
112 template <class T2>
113 static Vec<T, d, false> copy(T2* raw,
114 INVALID_WITH_VECTOR_REFERENCE u =
115 (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
116 Vec<T, d, false> ret;
117 for (int k = 0; k < d; k++) ret[k] = static_cast<T>(raw[k]);
118 return ret;
119 }
120
122 explicit Vec(T* raw, INVALID_WITH_VECTOR_VALUE u = (TYPENAME my_enable_if<ref, INVALID_WITH_VECTOR_VALUE>::TYPE()))
123 : x(raw) {}
124
126 Vec(INVALID_WITH_VECTOR_REFERENCE u = (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {}
127
129 Vec(T v0, INVALID_WITH_VECTOR_REFERENCE u = (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
130 for (int k = 0; k < d; k++) x[k] = v0;
131 }
132
134 Vec(T v1,
135 T v2,
136 INVALID_WITH_VECTOR_REFERENCE u = (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
137 TYPENAME seexpr_static_assert<d == 2, INVALID_WITH_DIMENSION>::TYPE();
138 x[0] = v1;
139 x[1] = v2;
140 }
141
143 Vec(T v1,
144 T v2,
145 T v3,
146 INVALID_WITH_VECTOR_REFERENCE u = (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
147 TYPENAME seexpr_static_assert<d == 3, INVALID_WITH_DIMENSION>::TYPE();
148 x[0] = v1;
149 x[1] = v2;
150 x[2] = v3;
151 }
152
154 Vec(T v1,
155 T v2,
156 T v3,
157 T v4,
158 INVALID_WITH_VECTOR_REFERENCE u = (TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
159 TYPENAME seexpr_static_assert<d == 4, INVALID_WITH_DIMENSION>::TYPE();
160 x[0] = v1;
161 x[1] = v2;
162 x[2] = v3;
163 x[3] = v4;
164 }
165 // Changed this to default. This is safe! for reference case it makes another reference
166 // for value it copies
168 // Vec(const Vec&)
169 //{TYPENAME static_assert<!ref,INVALID_WITH_VECTOR_REFERENCE>::TYPE();}
170
172 template <class T2, bool refother>
173 Vec(const Vec<T2, d, refother>& other,
174 INVALID_WITH_VECTOR_REFERENCE u =
175 (TYPENAME my_enable_if<!ref && refother != ref, INVALID_WITH_VECTOR_REFERENCE>::TYPE())) {
176 *this = other;
177 }
178
179 template <class T2, bool refother>
180 Vec& operator=(const Vec<T2, d, refother>& other) {
181 for (int k = 0; k < d; k++) x[k] = other[k];
182 return *this;
183 }
184
185 template <class Tother, bool refother>
186 bool operator==(const Vec<Tother, d, refother>& other) const {
187 for (int k = 0; k < d; k++)
188 if (x[k] != other[k]) return false;
189 return true;
190 }
191
192 template <class Tother, bool refother>
193 bool operator!=(const Vec<Tother, d, refother>& other) const {
194 return !(*this != other);
195 }
196
197 // non-const element access
198 T& operator[](const int i) { return x[i]; }
199
200 // const element access
201 const T& operator[](const int i) const { return x[i]; }
202
204 T length2() const {
205 T data[d];
206 for (int k = 0; k < d; k++) data[k] = x[k] * x[k];
207 return Reducer<T, d>::sum(data);
208 }
209
211 T length() const { return sqrt(length2()); }
212
214 T normalize() {
215 T l = length2();
216 if (l) {
217 l = sqrt(l);
218 *this /= l;
219 } else {
220 *this = T_VEC_VALUE((T)0);
221 x[0] = 1;
222 }
223 return l;
224 }
225
227 Vec<T, d, false> normalized() const {
228 Vec<T, d, false> other(*this);
229 other.normalize();
230 return other;
231 }
232
233 Vec& operator/=(const T val) {
234 T one_over_val = T(1) / val;
235 for (int k = 0; k < d; k++) x[k] *= one_over_val;
236 return *this;
237 }
238
239 Vec& operator*=(const T val) {
240 for (int k = 0; k < d; k++) x[k] *= val;
241 return *this;
242 }
243
244 template <bool refother>
245 Vec& operator+=(const Vec<T, d, refother>& other) {
246 for (int k = 0; k < d; k++) x[k] += other[k];
247 return *this;
248 }
249
250 template <bool refother>
251 Vec& operator-=(const Vec<T, d, refother>& other) {
252 for (int k = 0; k < d; k++) x[k] -= other[k];
253 return *this;
254 }
255
256 template <bool refother>
257 Vec& operator*=(const Vec<T, d, refother>& other) {
258 for (int k = 0; k < d; k++) x[k] *= other[k];
259 return *this;
260 }
261
262 template <bool refother>
263 Vec& operator/=(const Vec<T, d, refother>& other) {
264 for (int k = 0; k < d; k++) x[k] /= other[k];
265 return *this;
266 }
267
268 T_VEC_VALUE operator-() const {
269 T_VEC_VALUE val(*this);
270 for (int k = 0; k < d; k++) val[k] = -val[k];
271 return val;
272 }
273
274 template <bool refother>
275 bool operator==(const Vec<T, d, refother>& other) const {
276 bool equal = true;
277 for (int k = 0; k < d; k++) equal &= (x[k] == other[k]);
278 return equal;
279 }
280
281 template <bool refother>
282 bool operator!=(const Vec<T, d, refother>& other) const {
283 return !(*this == other);
284 }
285
286 T_VEC_VALUE operator*(T s) const {
287 T_VEC_VALUE val(*this);
288 val *= s;
289 return val;
290 }
291
292 T_VEC_VALUE operator/(T s) const {
293 T_VEC_VALUE val(*this);
294 val /= s;
295 return val;
296 }
297
298 template <bool refother>
299 T_VEC_VALUE operator+(const Vec<T, d, refother>& other) const {
300 T_VEC_VALUE val(*this);
301 val += other;
302 return val;
303 }
304
305 template <bool refother>
306 T_VEC_VALUE operator-(const Vec<T, d, refother>& other) const {
307 T_VEC_VALUE val(*this);
308 val -= other;
309 return val;
310 }
311
312 template <bool refother>
313 T_VEC_VALUE operator*(const Vec<T, d, refother>& other) const {
314 T_VEC_VALUE val(*this);
315 val *= other;
316 return val;
317 }
318
319 template <bool refother>
320 T_VEC_VALUE operator/(const Vec<T, d, refother>& other) const {
321 T_VEC_VALUE val(*this);
322 val /= other;
323 return val;
324 }
325
326 friend T_VEC_VALUE operator*(T s, const Vec& v) { return v * s; }
327
329 template <bool refother>
330 T dot(const Vec<T, d, refother>& o) const {
331 T data[d];
332 for (int k = 0; k < d; k++) data[k] = x[k] * o[k];
333 return Reducer<T, d>::sum(data);
334 }
335
337 template <bool refother>
338 T_VEC_VALUE cross(const Vec<T, 3, refother>& o) const {
339 TYPENAME seexpr_static_assert<d == 3, INVALID_WITH_DIMENSION>::TYPE();
340 return T_VEC_VALUE(x[1] * o[2] - x[2] * o[1], x[2] * o[0] - x[0] * o[2], x[0] * o[1] - x[1] * o[0]);
341 }
342
344 T_VEC_VALUE orthogonal() const {
345 TYPENAME seexpr_static_assert<d == 3, INVALID_WITH_DIMENSION>::TYPE();
346 return T_VEC_VALUE(x[1] + x[2], x[2] - x[0], -x[0] - x[1]);
347 }
348
353 template <bool refother>
354 T angle(const Vec<T, 3, refother>& o) const {
355 TYPENAME seexpr_static_assert<d == 3, INVALID_WITH_DIMENSION>::TYPE();
356 T l = length() * o.length();
357 if (l == 0) return 0;
358 return acos(dot(o) / l);
359 }
360
365 template <bool refother>
366 T_VEC_VALUE rotateBy(const Vec<T, 3, refother>& axis, T angle) const {
367 TYPENAME seexpr_static_assert<d == 3, INVALID_WITH_DIMENSION>::TYPE();
368 double c = cos(angle), s = sin(angle);
369 return c * (*this) + (1 - c) * dot(axis) * axis - s * cross(axis);
370 }
371 };
372
374 template <class T, int d, bool r>
375 std::ostream& operator<<(std::ostream& out, const Vec<T, d, r>& val) {
376 if (d > 0) out << "(" << val[0];
377 for (int k = 1; k < d; k++) out << "," << val[k];
378 out << ")";
379 return out;
380 }
381
382 using Vec1d = Vec<double, 1, false>;
383 using Vec2d = Vec<double, 2, false>;
384 using Vec3d = Vec<double, 3, false>;
385 using Vec4d = Vec<double, 4, false>;
386 using Vec1f = Vec<float, 1, false>;
387 using Vec2f = Vec<float, 2, false>;
388 using Vec3f = Vec<float, 3, false>;
389 using Vec4f = Vec<float, 4, false>;
390 using Vec1dRef = Vec<double, 1, true>;
391 using Vec2dRef = Vec<double, 2, true>;
392 using Vec3dRef = Vec<double, 3, true>;
393 using Vec4dRef = Vec<double, 4, true>;
394 using Vec1fRef = Vec<float, 1, true>;
395 using Vec2fRef = Vec<float, 2, true>;
396 using Vec3fRef = Vec<float, 3, true>;
397 using Vec4fRef = Vec<float, 4, true>;
398 using Vec1dConstRef = Vec<const double, 1, true>;
399 using Vec2dConstRef = Vec<const double, 2, true>;
400 using Vec3dConstRef = Vec<const double, 3, true>;
401 using Vec4dConstRef = Vec<const double, 4, true>;
402 using Vec1fConstRef = Vec<const float, 1, true>;
403 using Vec2fConstRef = Vec<const float, 2, true>;
404 using Vec3fConstRef = Vec<const float, 3, true>;
405 using Vec4fConstRef = Vec<const float, 4, true>;
406 }
407 #endif
SeExpr2::static_if::TYPE
T1 TYPE
Definition: Vec.h:60
SeExpr2::Vec::operator/
T_VEC_VALUE operator/(const Vec< T, d, refother > &other) const
Definition: Vec.h:320
SeExpr2::operator<<
std::ostream & operator<<(std::ostream &out, const Vec< T, d, r > &val)
Output stream.
Definition: Vec.h:375
SeExpr2::Vec::operator*=
Vec & operator*=(const Vec< T, d, refother > &other)
Definition: Vec.h:257
SeExpr2::Vec::Vec
Vec(T v0, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Convenience constant vector initialization (valid for any d)
Definition: Vec.h:129
SeExpr2::Vec::operator+=
Vec & operator+=(const Vec< T, d, refother > &other)
Definition: Vec.h:245
SeExpr2::Vec::INVALID_WITH_DIMENSION
Definition: Vec.h:102
SeExpr2::Reducer< T, 2 >::sum
static T sum(T *data)
Definition: Vec.h:84
SeExpr2::Vec::Vec
Vec(T v1, T v2, T v3, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Convenience 3 vector initialization (only for d==3)
Definition: Vec.h:143
SeExpr2::Vec::copy
static Vec< T, d, false > copy(T2 *raw, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Initialize vector value using raw memory.
Definition: Vec.h:113
SeExpr2::Vec
Definition: Vec.h:98
SeExpr2::Vec::operator*
friend T_VEC_VALUE operator*(T s, const Vec &v)
Definition: Vec.h:326
SeExpr2::Vec::normalized
Vec< T, d, false > normalized() const
Return a copy of the vector that is normalized.
Definition: Vec.h:227
SeExpr2::Vec::dot
T dot(const Vec< T, d, refother > &o) const
Definition: Vec.h:330
SeExpr2::Vec::operator!=
bool operator!=(const Vec< Tother, d, refother > &other) const
Definition: Vec.h:193
SeExpr2::Vec::length2
T length2() const
Square of euclidean (2) norm.
Definition: Vec.h:204
TYPENAME
#define TYPENAME
Definition: Vec.h:29
SeExpr2::Vec::cross
T_VEC_VALUE cross(const Vec< T, 3, refother > &o) const
Definition: Vec.h:338
SeExpr2::Vec::INVALID_WITH_VECTOR_VALUE
Definition: Vec.h:100
SeExpr2::Vec::Vec
Vec(INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Empty constructor (this is invalid for a reference type)
Definition: Vec.h:126
SeExpr2::static_if< false, T1, T2 >::TYPE
T2 TYPE
Definition: Vec.h:65
SeExpr2::Vec::operator-
T_VEC_VALUE operator-(const Vec< T, d, refother > &other) const
Definition: Vec.h:306
SeExpr2::Vec::operator*
T_VEC_VALUE operator*(T s) const
Definition: Vec.h:286
SeExpr2::seexpr_static_assert< true, T >::TYPE
T TYPE
Definition: Vec.h:41
Platform.h
Platform-specific classes, functions, and includes.
SeExpr2::Reducer< T, 3 >::sum
static T sum(T *data)
Definition: Vec.h:88
SeExpr2::Vec::operator/
T_VEC_VALUE operator/(T s) const
Definition: Vec.h:292
SeExpr2::Vec::Vec
Vec(const Vec< T2, d, refother > &other, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref &&refother !=ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Copy construct. Only valid if we are not going to be a reference data!
Definition: Vec.h:173
SeExpr2::Vec::operator[]
const T & operator[](const int i) const
Definition: Vec.h:201
SeExpr2::static_if
Static conditional type true case.
Definition: Vec.h:59
SeExpr2
Definition: Context.h:22
SeExpr2::Vec::operator/=
Vec & operator/=(const T val)
Definition: Vec.h:233
SeExpr2::Reducer::sum
static T sum(T *data)
Definition: Vec.h:72
SeExpr2::Vec::operator/=
Vec & operator/=(const Vec< T, d, refother > &other)
Definition: Vec.h:263
SeExpr2::Vec::operator==
bool operator==(const Vec< T, d, refother > &other) const
Definition: Vec.h:275
SeExpr2::my_enable_if
Enable_if success case (can find the type TYPE)
Definition: Vec.h:46
SeExpr2::Vec::operator*
T_VEC_VALUE operator*(const Vec< T, d, refother > &other) const
Definition: Vec.h:313
SeExpr2::Vec::operator!=
bool operator!=(const Vec< T, d, refother > &other) const
Definition: Vec.h:282
SeExpr2::Reducer< T, 1 >::sum
static T sum(T *data)
Definition: Vec.h:80
SeExpr2::my_enable_if::TYPE
T TYPE
Definition: Vec.h:47
SeExpr2::Vec::operator-
T_VEC_VALUE operator-() const
Definition: Vec.h:268
SeExpr2::Vec::rotateBy
T_VEC_VALUE rotateBy(const Vec< T, 3, refother > &axis, T angle) const
Definition: Vec.h:366
SeExpr2::Vec::operator-=
Vec & operator-=(const Vec< T, d, refother > &other)
Definition: Vec.h:251
SeExpr2::Vec::Vec
Vec(T v1, T v2, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Convenience 2 vector initialization (only for d==2)
Definition: Vec.h:134
SeExpr2::Vec::operator==
bool operator==(const Vec< Tother, d, refother > &other) const
Definition: Vec.h:186
SeExpr2::Vec::operator[]
T & operator[](const int i)
Definition: Vec.h:198
SeExpr2::Vec::normalize
T normalize()
Normalize in place and return the 2-norm before normalization.
Definition: Vec.h:214
SeExpr2::Vec::Vec
Vec(T *raw, INVALID_WITH_VECTOR_VALUE u=(TYPENAME my_enable_if< ref, INVALID_WITH_VECTOR_VALUE >::TYPE()))
Initialize vector to be reference to plain raw data.
Definition: Vec.h:122
SeExpr2::Vec::orthogonal
T_VEC_VALUE orthogonal() const
Definition: Vec.h:344
SeExpr2::Vec::x
static_if< ref, T *, T[d]>::TYPE x
internal data (either an explicit arary or a pointer to raw data)
Definition: Vec.h:105
SeExpr2::Reducer
Definition: Vec.h:71
SeExpr2::Vec::T_VEC_REF
Vec< T, d, true > T_VEC_REF
Definition: Vec.h:109
SeExpr2::Vec::Vec
Vec(T v1, T v2, T v3, T v4, INVALID_WITH_VECTOR_REFERENCE u=(TYPENAME my_enable_if<!ref, INVALID_WITH_VECTOR_REFERENCE >::TYPE()))
Convenience 4 vector initialization (only for d==4)
Definition: Vec.h:154
sin
* sin(val)/val" </pre> we would get <pre> | | | | | </pre> or if we did <pre> ./asciiGraph "x-3" </pre> we'd get <pre> | | ------------------------------|----------------- | | | | | </pre> <h2>Implement the subclass</h2> First we subclass Expression and give it a const ructor
SeExpr2::Vec::angle
T angle(const Vec< T, 3, refother > &o) const
Definition: Vec.h:354
SeExpr2::seexpr_static_assert
Static assert error case (false)
Definition: Vec.h:37
SeExpr2::Vec::T_VEC_VALUE
Vec< T, d, false > T_VEC_VALUE
Definition: Vec.h:108
SeExpr2::Reducer< T, 4 >::sum
static T sum(T *data)
Definition: Vec.h:92
SeExpr2::Vec::operator=
Vec & operator=(const Vec< T2, d, refother > &other)
Definition: Vec.h:180
SeExpr2::Vec::INVALID_WITH_VECTOR_REFERENCE
Definition: Vec.h:101
SeExpr2::Vec::operator+
T_VEC_VALUE operator+(const Vec< T, d, refother > &other) const
Definition: Vec.h:299
SeExpr2::Vec::length
T length() const
Euclidean (2) norm.
Definition: Vec.h:211
SeExpr2::Vec::operator*=
Vec & operator*=(const T val)
Definition: Vec.h:239