KSeExpr  4.0.4.0
Vec.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 Disney Enterprises, Inc.
2 // SPDX-License-Identifier: LicenseRef-Apache-2.0
3 // SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4 // SPDX-License-Identifier: GPL-3.0-or-later
5 
6 #pragma once
7 
8 #include <array>
9 #include <cmath>
10 #include <iostream>
11 #include <numeric>
12 #include <type_traits>
13 
14 
15 //#############################################################################
16 // Template Metaprogramming Helpers
17 namespace KSeExpr
18 {
20 template<bool c, class T1, class T2> struct static_if {
21  using TYPE = T1;
22 };
24 template<class T1, class T2> struct static_if<false, T1, T2> {
25  using TYPE = T2;
26 };
27 
30 template<class T, size_t d, bool ref = false> class Vec
31 {
34 
35 public:
38 
40  template<class T2> static Vec<T, d, false> copy(T2 *raw)
41  {
42  static_assert(!ref, "Cannot be used with vector references");
43  Vec<T, d, false> ret;
44  for (size_t k = 0; k < d; k++)
45  ret[k] = static_cast<T>(raw[k]);
46  return ret;
47  }
48 
50  explicit Vec(T *raw)
51  : x(raw)
52  {
53  static_assert(ref, "Constructor cannot be used with vector values");
54  }
55 
57  Vec()
58  {
59  static_assert(!ref, "Constructor cannot be used with vector references");
60  }
61 
63  Vec(T v0)
64  {
65  static_assert(!ref, "Constructor cannot be used with vector references");
66  for (size_t k = 0; k < d; k++)
67  x[k] = v0;
68  }
69 
71  Vec(T v1, T v2)
72  {
73  static_assert(!ref, "Constructor cannot be used with vector references");
74  static_assert(d == 2, "Invalid constructor for dimension");
75  x[0] = v1;
76  x[1] = v2;
77  }
78 
80  Vec(T v1, T v2, T v3)
81  {
82  static_assert(!ref, "Constructor cannot be used with vector references");
83  static_assert(d == 3, "Invalid constructor for dimension");
84  x[0] = v1;
85  x[1] = v2;
86  x[2] = v3;
87  }
88 
90  Vec(T v1, T v2, T v3, T v4)
91  {
92  static_assert(!ref, "Constructor cannot be used with vector references");
93  static_assert(d == 4, "Invalid constructor for dimension");
94  x[0] = v1;
95  x[1] = v2;
96  x[2] = v3;
97  x[3] = v4;
98  }
99  // Changed this to default. This is safe! for reference case it makes another reference
100  // for value it copies
102  // Vec(const Vec&)
103 
105  template<class T2, bool refother> Vec(const Vec<T2, d, refother> &other)
106  {
107  static_assert(!ref, "Cannot be used with vector references");
108  *this = other;
109  }
110 
111  template<class T2, bool refother> Vec &operator=(const Vec<T2, d, refother> &other)
112  {
113  for (size_t k = 0; k < d; k++)
114  x[k] = other[k];
115  return *this;
116  }
117 
118  template<class Tother, bool refother> bool operator==(const Vec<Tother, d, refother> &other) const
119  {
120  for (size_t k = 0; k < d; k++)
121  if (x[k] != other[k])
122  return false;
123  return true;
124  }
125 
126  template<class Tother, bool refother> bool operator!=(const Vec<Tother, d, refother> &other) const
127  {
128  return !(*this != other);
129  }
130 
131  // non-const element access
132  T &operator[](const int i)
133  {
134  return x[i];
135  }
136 
137  // const element access
138  const T &operator[](const int i) const
139  {
140  return x[i];
141  }
142 
144  T length2() const
145  {
146  std::array<T, d> data;
147  for (size_t k = 0; k < d; k++)
148  data[k] = x[k] * x[k];
149  return std::accumulate(data.cbegin(), data.cend(), static_cast<T>(0));
150  }
151 
153  T length() const
154  {
155  return sqrt(length2());
156  }
157 
160  {
161  T l = length2();
162  if (l) {
163  l = sqrt(l);
164  *this /= l;
165  } else {
166  *this = T_VEC_VALUE((T)0);
167  x[0] = 1;
168  }
169  return l;
170  }
171 
174  {
175  Vec<T, d, false> other(*this);
176  other.normalize();
177  return other;
178  }
179 
180  Vec &operator/=(const T val)
181  {
182  T one_over_val = T(1) / val;
183  for (size_t k = 0; k < d; k++)
184  x[k] *= one_over_val;
185  return *this;
186  }
187 
188  Vec &operator*=(const T val)
189  {
190  for (size_t k = 0; k < d; k++)
191  x[k] *= val;
192  return *this;
193  }
194 
195  template<bool refother> Vec &operator+=(const Vec<T, d, refother> &other)
196  {
197  for (size_t k = 0; k < d; k++)
198  x[k] += other[k];
199  return *this;
200  }
201 
202  template<bool refother> Vec &operator-=(const Vec<T, d, refother> &other)
203  {
204  for (size_t k = 0; k < d; k++)
205  x[k] -= other[k];
206  return *this;
207  }
208 
209  template<bool refother> Vec &operator*=(const Vec<T, d, refother> &other)
210  {
211  for (size_t k = 0; k < d; k++)
212  x[k] *= other[k];
213  return *this;
214  }
215 
216  template<bool refother> Vec &operator/=(const Vec<T, d, refother> &other)
217  {
218  for (size_t k = 0; k < d; k++)
219  x[k] /= other[k];
220  return *this;
221  }
222 
224  {
225  T_VEC_VALUE val(*this);
226  for (size_t k = 0; k < d; k++)
227  val[k] = -val[k];
228  return val;
229  }
230 
231  template<bool refother> bool operator==(const Vec<T, d, refother> &other) const
232  {
233  bool equal = true;
234  for (size_t k = 0; k < d; k++)
235  equal &= (x[k] == other[k]);
236  return equal;
237  }
238 
239  template<bool refother> bool operator!=(const Vec<T, d, refother> &other) const
240  {
241  return !(*this == other);
242  }
243 
245  {
246  T_VEC_VALUE val(*this);
247  val *= s;
248  return val;
249  }
250 
252  {
253  T_VEC_VALUE val(*this);
254  val /= s;
255  return val;
256  }
257 
258  template<bool refother> T_VEC_VALUE operator+(const Vec<T, d, refother> &other) const
259  {
260  T_VEC_VALUE val(*this);
261  val += other;
262  return val;
263  }
264 
265  template<bool refother> T_VEC_VALUE operator-(const Vec<T, d, refother> &other) const
266  {
267  T_VEC_VALUE val(*this);
268  val -= other;
269  return val;
270  }
271 
272  template<bool refother> T_VEC_VALUE operator*(const Vec<T, d, refother> &other) const
273  {
274  T_VEC_VALUE val(*this);
275  val *= other;
276  return val;
277  }
278 
279  template<bool refother> T_VEC_VALUE operator/(const Vec<T, d, refother> &other) const
280  {
281  T_VEC_VALUE val(*this);
282  val /= other;
283  return val;
284  }
285 
286  friend T_VEC_VALUE operator*(T s, const Vec &v)
287  {
288  return v * s;
289  }
290 
292  template<bool refother> T dot(const Vec<T, d, refother> &o) const
293  {
294  std::array<T, d> data;
295  for (size_t k = 0; k < d; k++)
296  data[k] = x[k] * o[k];
297  return std::accumulate(data.cbegin(), data.cend(), static_cast<T>(0));
298  }
299 
301  template<bool refother> T_VEC_VALUE cross(const Vec<T, 3, refother> &o) const
302  {
303  static_assert(d == 3, "Invalid constructor for dimension"); 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]);
304  }
305 
308  {
309  static_assert(d == 3, "Invalid constructor for dimension");
310  return T_VEC_VALUE(x[1] + x[2], x[2] - x[0], -x[0] - x[1]);
311  }
312 
317  template<bool refother> T angle(const Vec<T, 3, refother> &o) const
318  {
319  static_assert(d == 3, "Invalid constructor for dimension");
320  T l = length() * o.length();
321  if (l == 0)
322  return 0;
323  return acos(dot(o) / l);
324  }
325 
330  template<bool refother> T_VEC_VALUE rotateBy(const Vec<T, 3, refother> &axis, T angle) const
331  {
332  static_assert(d == 3, "Invalid constructor for dimension");
333  double c = cos(angle);
334  double s = sin(angle);
335  return c * (*this) + (1 - c) * dot(axis) * axis - s * cross(axis);
336  }
337 };
338 
340 template<class T, size_t d, bool r> std::ostream &operator<<(std::ostream &out, const Vec<T, d, r> &val)
341 {
342  if (d > 0)
343  out << "(" << val[0];
344  for (size_t k = 1; k < d; k++)
345  out << "," << val[k];
346  out << ")";
347  return out;
348 }
349 
374 } // namespace KSeExpr
T_VEC_VALUE operator-(const Vec< T, d, refother > &other) const
Definition: Vec.h:265
T_VEC_VALUE operator+(const Vec< T, d, refother > &other) const
Definition: Vec.h:258
Vec & operator=(const Vec< T2, d, refother > &other)
Definition: Vec.h:111
T dot(const Vec< T, d, refother > &o) const
Definition: Vec.h:292
T & operator[](const int i)
Definition: Vec.h:132
static Vec< T, d, false > copy(T2 *raw)
Initialize vector value using raw memory.
Definition: Vec.h:40
bool operator!=(const Vec< Tother, d, refother > &other) const
Definition: Vec.h:126
friend T_VEC_VALUE operator*(T s, const Vec &v)
Definition: Vec.h:286
Vec()
Empty constructor (this is invalid for a reference type)
Definition: Vec.h:57
T length2() const
Square of euclidean (2) norm.
Definition: Vec.h:144
T_VEC_VALUE operator*(const Vec< T, d, refother > &other) const
Definition: Vec.h:272
Vec(T *raw)
Initialize vector to be reference to plain raw data.
Definition: Vec.h:50
Vec(T v1, T v2, T v3, T v4)
Convenience 4 vector initialization (only for d==4)
Definition: Vec.h:90
Vec & operator/=(const Vec< T, d, refother > &other)
Definition: Vec.h:216
Vec & operator+=(const Vec< T, d, refother > &other)
Definition: Vec.h:195
Vec(const Vec< T2, d, refother > &other)
Copy construct. Only valid if we are not going to be a reference data!
Definition: Vec.h:105
T_VEC_VALUE operator/(const Vec< T, d, refother > &other) const
Definition: Vec.h:279
bool operator==(const Vec< T, d, refother > &other) const
Definition: Vec.h:231
Vec(T v1, T v2, T v3)
Convenience 3 vector initialization (only for d==3)
Definition: Vec.h:80
bool operator!=(const Vec< T, d, refother > &other) const
Definition: Vec.h:239
Vec< T, d, false > normalized() const
Return a copy of the vector that is normalized.
Definition: Vec.h:173
bool operator==(const Vec< Tother, d, refother > &other) const
Definition: Vec.h:118
Vec(T v0)
Convenience constant vector initialization (valid for any d)
Definition: Vec.h:63
Vec & operator*=(const Vec< T, d, refother > &other)
Definition: Vec.h:209
Vec< T, d, false > T_VEC_VALUE
Definition: Vec.h:36
T angle(const Vec< T, 3, refother > &o) const
Definition: Vec.h:317
T_VEC_VALUE rotateBy(const Vec< T, 3, refother > &axis, T angle) const
Definition: Vec.h:330
T_VEC_VALUE operator-() const
Definition: Vec.h:223
T_VEC_VALUE orthogonal() const
Definition: Vec.h:307
T normalize()
Normalize in place and return the 2-norm before normalization.
Definition: Vec.h:159
T length() const
Euclidean (2) norm.
Definition: Vec.h:153
static_if< ref, T *, std::array< T, d > >::TYPE x
internal data (either an explicit arary or a pointer to raw data)
Definition: Vec.h:33
Vec(T v1, T v2)
Convenience 2 vector initialization (only for d==2)
Definition: Vec.h:71
T_VEC_VALUE operator*(T s) const
Definition: Vec.h:244
Vec & operator/=(const T val)
Definition: Vec.h:180
T_VEC_VALUE operator/(T s) const
Definition: Vec.h:251
Vec & operator*=(const T val)
Definition: Vec.h:188
Vec & operator-=(const Vec< T, d, refother > &other)
Definition: Vec.h:202
T_VEC_VALUE cross(const Vec< T, 3, refother > &o) const
Definition: Vec.h:301
const T & operator[](const int i) const
Definition: Vec.h:138
std::ostream & operator<<(std::ostream &out, const Vec< T, d, r > &val)
Output stream.
Definition: Vec.h:340
Static conditional type true case.
Definition: Vec.h:20