VectorN-Impl.h
Go to the documentation of this file.
1 /*************************************************************************
2 > File Name: VectorN-Impl.h
3 > Project Name: CubbyFlow
4 > Author: Chan-Ho Chris Ohk
5 > Purpose: General purpose dynamically-sized N-D vector class.
6 > Created Time: 2017/09/28
7 > Copyright (c) 2018, Chan-Ho Chris Ohk
8 *************************************************************************/
9 #ifndef CUBBYFLOW_VECTORN_IMPL_H
10 #define CUBBYFLOW_VECTORN_IMPL_H
11 
12 #include <Core/Math/MathUtils.h>
13 #include <Core/Utils/Parallel.h>
14 
15 namespace CubbyFlow
16 {
17  // MARK: VectorN
18  template <typename T>
20  {
21  // Do nothing
22  }
23 
24  template <typename T>
25  VectorN<T>::VectorN(size_t n, const T& val) : m_elements(n, val)
26  {
27  // Do nothing
28  }
29 
30  template <typename T>
31  template <typename U>
32  VectorN<T>::VectorN(const std::initializer_list<U>& list)
33  {
34  Set(list);
35  }
36 
37  template <typename T>
38  template <typename E>
40  {
41  Set(other);
42  }
43 
44  template <typename T>
46  {
47  Set(other);
48  }
49 
50  template <typename T>
51  VectorN<T>::VectorN(VectorN&& other) noexcept
52  {
53  (*this) = std::move(other);
54  }
55 
56  template <typename T>
57  void VectorN<T>::Resize(size_t n, const T& val)
58  {
59  m_elements.resize(n, val);
60  }
61 
62  template <typename T>
64  {
65  m_elements.clear();
66  }
67 
68  template <typename T>
69  void VectorN<T>::Set(const T& s)
70  {
71  ParallelFill(begin(), end(), s);
72  }
73 
74  template <typename T>
75  template <typename U>
76  void VectorN<T>::Set(const std::initializer_list<U>& list)
77  {
78  m_elements = list;
79  }
80 
81  template <typename T>
82  template <typename E>
84  {
85  Resize(other.size());
86 
87  // Parallel evaluation of the expression
88  const E& expression = other();
89  ParallelForEachIndex([&](size_t i) { m_elements[i] = expression[i]; });
90  }
91 
92  template <typename T>
93  void VectorN<T>::Append(const T& val)
94  {
95  m_elements.push_back(val);
96  }
97 
98  template <typename T>
100  {
101  std::swap(other.m_elements, m_elements);
102  }
103 
104  template <typename T>
106  {
107  Set(T(0));
108  }
109 
110  template <typename T>
112  {
113  IDiv(Length());
114  }
115 
116  template <typename T>
117  size_t VectorN<T>::size() const
118  {
119  return m_elements.size();
120  }
121 
122  template <typename T>
124  {
125  return m_elements.data();
126  }
127 
128  template <typename T>
129  const T* VectorN<T>::data() const
130  {
131  return m_elements.data();
132  }
133 
134  template <typename T>
136  {
137  return m_elements.begin();
138  }
139 
140  template <typename T>
142  {
143  return m_elements.cbegin();
144  }
145 
146  template <typename T>
148  {
149  return m_elements.end();
150  }
151 
152  template <typename T>
154  {
155  return m_elements.cend();
156  }
157 
158  template <typename T>
160  {
161  return ArrayAccessor1<T>(size(), data());
162  }
163 
164  template <typename T>
166  {
167  return ConstArrayAccessor1<T>(size(), data());
168  }
169 
170  template <typename T>
171  T VectorN<T>::At(size_t i) const
172  {
173  return m_elements[i];
174  }
175 
176  template <typename T>
177  T& VectorN<T>::At(size_t i)
178  {
179  return m_elements[i];
180  }
181 
182  template <typename T>
183  T VectorN<T>::Sum() const
184  {
185  return ParallelReduce(ZERO_SIZE, size(), T(0),
186  [&](size_t start, size_t end, T init)
187  {
188  T result = init;
189 
190  for (size_t i = start; i < end; ++i)
191  {
192  result += m_elements[i];
193  }
194 
195  return result;
196  }, std::plus<T>());
197  }
198 
199  template <typename T>
200  T VectorN<T>::Avg() const
201  {
202  return Sum() / static_cast<T>(size());
203  }
204 
205  template <typename T>
206  T VectorN<T>::Min() const
207  {
208  const T& (*_min)(const T&, const T&) = std::min<T>;
209 
210  return ParallelReduce(ZERO_SIZE, size(), std::numeric_limits<T>::max(),
211  [&](size_t start, size_t end, T init)
212  {
213  T result = init;
214 
215  for (size_t i = start; i < end; ++i)
216  {
217  result = std::min(result, m_elements[i]);
218  }
219 
220  return result;
221  }, _min);
222  }
223 
224  template <typename T>
225  T VectorN<T>::Max() const
226  {
227  const T& (*_max)(const T&, const T&) = std::max<T>;
228 
229  return ParallelReduce(ZERO_SIZE, size(), std::numeric_limits<T>::min(),
230  [&](size_t start, size_t end, T init)
231  {
232  T result = init;
233 
234  for (size_t i = start; i < end; ++i)
235  {
236  result = std::max(result, m_elements[i]);
237  }
238 
239  return result;
240  }, _max);
241  }
242 
243  template <typename T>
245  {
246  return ParallelReduce(ZERO_SIZE, size(), std::numeric_limits<T>::max(),
247  [&](size_t start, size_t end, T init)
248  {
249  T result = init;
250 
251  for (size_t i = start; i < end; ++i)
252  {
253  result = CubbyFlow::AbsMin(result, m_elements[i]);
254  }
255 
256  return result;
257  }, CubbyFlow::AbsMin<T>);
258  }
259 
260  template <typename T>
262  {
263  return ParallelReduce(ZERO_SIZE, size(), T(0),
264  [&](size_t start, size_t end, T init)
265  {
266  T result = init;
267 
268  for (size_t i = start; i < end; ++i)
269  {
270  result = CubbyFlow::AbsMax(result, m_elements[i]);
271  }
272 
273  return result;
274  }, CubbyFlow::AbsMax<T>);
275  }
276 
277  template <typename T>
279  {
280  auto iter = std::max_element(begin(), end(), [](const T& a, const T& b)
281  {
282  return std::fabs(a) < std::fabs(b);
283  });
284 
285  return iter - begin();
286  }
287 
288  template <typename T>
290  {
291  auto iter = std::max_element(begin(), end(), [](const T& a, const T& b)
292  {
293  return std::fabs(a) > std::fabs(b);
294  });
295 
296  return iter - begin();
297  }
298 
299  template <typename T>
301  {
302  T len = Length();
303  return VectorScalarDiv<T, VectorN>(*this, len);
304  }
305 
306  template <typename T>
308  {
309  return std::sqrt(LengthSquared());
310  }
311 
312  template <typename T>
314  {
315  return Dot(*this);
316  }
317 
318  template <typename T>
319  template <typename E>
320  T VectorN<T>::DistanceTo(const E& other) const
321  {
322  return std::sqrt(DistanceSquaredTo(other));
323  }
324 
325  template <typename T>
326  template <typename E>
327  T VectorN<T>::DistanceSquaredTo(const E& other) const
328  {
329  assert(size() == other.size());
330 
331  return ParallelReduce(ZERO_SIZE, size(), T(0),
332  [&](size_t start, size_t end, T init)
333  {
334  T result = init;
335 
336  for (size_t i = start; i < end; ++i)
337  {
338  T diff = (m_elements[i] - other[i]);
339  result += diff * diff;
340  }
341 
342  return result;
343  }, std::plus<T>());
344  }
345 
346  template <typename T>
347  template <typename U>
349  {
350  return VectorTypeCast<U, VectorN<T>, T>(*this);
351  }
352 
353  template <typename T>
354  template <typename E>
355  bool VectorN<T>::IsEqual(const E& other) const
356  {
357  if (size() != other.size())
358  {
359  return false;
360  }
361 
362  for (size_t i = 0; i < size(); ++i)
363  {
364  if (At(i) != other[i])
365  {
366  return false;
367  }
368  }
369 
370  return true;
371  }
372 
373  template <typename T>
374  template <typename E>
375  bool VectorN<T>::IsSimilar(const E& other, T epsilon) const
376  {
377  if (size() != other.size())
378  {
379  return false;
380  }
381 
382  for (size_t i = 0; i < size(); ++i)
383  {
384  if (std::fabs(At(i) - other[i]) > epsilon)
385  {
386  return false;
387  }
388  }
389 
390  return true;
391  }
392 
393  template <typename T>
394  template <typename E>
396  {
397  return VectorAdd<T, VectorN, E>(*this, v);
398  }
399 
400  template <typename T>
402  {
403  return VectorScalarAdd<T, VectorN>(*this, s);
404  }
405 
406  template <typename T>
407  template <typename E>
409  {
410  return VectorSub<T, VectorN, E>(*this, v);
411  }
412 
413  template <typename T>
415  {
416  return VectorScalarSub<T, VectorN>(*this, s);
417  }
418 
419  template <typename T>
420  template <typename E>
422  {
423  return VectorMul<T, VectorN, E>(*this, v);
424  }
425 
426  template <typename T>
428  {
429  return VectorScalarMul<T, VectorN>(*this, s);
430  }
431 
432  template <typename T>
433  template <typename E>
435  {
436  return VectorDiv<T, VectorN, E>(*this, v);
437  }
438 
439  template <typename T>
441  {
442  return VectorScalarDiv<T, VectorN>(*this, s);
443  }
444 
445  template <typename T>
446  template <typename E>
447  T VectorN<T>::Dot(const E& v) const
448  {
449  assert(size() == v.size());
450 
451  return ParallelReduce(ZERO_SIZE, size(), T(0),
452  [&](size_t start, size_t end, T init)
453  {
454  T result = init;
455 
456  for (size_t i = start; i < end; ++i)
457  {
458  result += m_elements[i] * v[i];
459  }
460 
461  return result;
462  }, std::plus<T>());
463  }
464 
465  template <typename T>
467  {
468  return VectorScalarRSub<T, VectorN>(*this, s);
469  }
470 
471  template <typename T>
472  template <typename E>
474  {
475  return VectorSub<T, VectorN, E>(v, *this);
476  }
477 
478  template <typename T>
480  {
481  return VectorScalarRDiv<T, VectorN>(*this, s);
482  }
483 
484  template <typename T>
485  template <typename E>
487  {
488  return VectorDiv<T, VectorN, E>(v, *this);
489  }
490 
491  template <typename T>
492  void VectorN<T>::IAdd(const T& s)
493  {
494  Set(Add(s));
495  }
496 
497  template <typename T>
498  template <typename E>
499  void VectorN<T>::IAdd(const E& v)
500  {
501  Set(Add(v));
502  }
503 
504  template <typename T>
505  void VectorN<T>::ISub(const T& s)
506  {
507  Set(Sub(s));
508  }
509 
510  template <typename T>
511  template <typename E>
512  void VectorN<T>::ISub(const E& v)
513  {
514  Set(Sub(v));
515  }
516 
517  template <typename T>
518  void VectorN<T>::IMul(const T& s)
519  {
520  Set(Mul(s));
521  }
522 
523  template <typename T>
524  template <typename E>
525  void VectorN<T>::IMul(const E& v)
526  {
527  Set(Mul(v));
528  }
529 
530  template <typename T>
531  void VectorN<T>::IDiv(const T& s)
532  {
533  Set(Div(s));
534  }
535 
536  template <typename T>
537  template <typename E>
538  void VectorN<T>::IDiv(const E& v)
539  {
540  Set(Div(v));
541  }
542 
543  template <typename T>
544  template <typename Callback>
545  void VectorN<T>::ForEach(Callback func) const
546  {
547  ConstAccessor().ForEach(func);
548  }
549 
550  template <typename T>
551  template <typename Callback>
552  void VectorN<T>::ForEachIndex(Callback func) const
553  {
554  ConstAccessor().ForEachIndex(func);
555  }
556 
557  template <typename T>
558  template <typename Callback>
559  void VectorN<T>::ParallelForEach(Callback func)
560  {
561  Accessor().ParallelForEach(func);
562  }
563 
564  template <typename T>
565  template <typename Callback>
566  void VectorN<T>::ParallelForEachIndex(Callback func) const
567  {
568  ConstAccessor().ParallelForEachIndex(func);
569  }
570 
571  template <typename T>
572  T VectorN<T>::operator[](size_t i) const
573  {
574  return m_elements[i];
575  }
576 
577  template <typename T>
579  {
580  return m_elements[i];
581  }
582 
583  template <typename T>
584  template <typename U>
585  VectorN<T>& VectorN<T>::operator=(const std::initializer_list<U>& list)
586  {
587  Set(list);
588  return *this;
589  }
590 
591  template <typename T>
592  template <typename E>
594  {
595  Set(other);
596  return *this;
597  }
598 
599  template <typename T>
601  {
602  Set(other);
603  return *this;
604  }
605 
606  template <typename T>
608  {
609  m_elements = std::move(other.m_elements);
610  return *this;
611  }
612 
613  template <typename T>
615  {
616  IAdd(s);
617  return *this;
618  }
619 
620  template <typename T>
621  template <typename E>
623  {
624  IAdd(v);
625  return *this;
626  }
627 
628  template <typename T>
630  {
631  ISub(s);
632  return *this;
633  }
634 
635  template <typename T>
636  template <typename E>
638  {
639  ISub(v);
640  return *this;
641  }
642 
643  template <typename T>
645  {
646  IMul(s);
647  return *this;
648  }
649 
650  template <typename T>
651  template <typename E>
653  {
654  IMul(v);
655  return *this;
656  }
657 
658  template <typename T>
660  {
661  IDiv(s);
662  return *this;
663  }
664 
665  template <typename T>
666  template <typename E>
668  {
669  IDiv(v);
670  return *this;
671  }
672 
673  template <typename T>
674  template <typename E>
675  bool VectorN<T>::operator==(const E& v) const
676  {
677  return IsEqual(v);
678  }
679 
680  template <typename T>
681  template <typename E>
682  bool VectorN<T>::operator!=(const E& v) const
683  {
684  return !IsEqual(v);
685  }
686 }
687 
688 #endif
T * data()
Returns the raw pointer to the vector data.
Definition: VectorN-Impl.h:123
void ForEach(Callback func) const
Iterates the vector and invoke given func for each element.
Definition: VectorN-Impl.h:545
T AbsMin(T x, T y)
Returns the absolute minimum value among the two inputs.
Definition: MathUtils-Impl.h:39
void ParallelForEachIndex(Callback func) const
Iterates the vector and invoke given func for each index in parallel using multi-threading.
Definition: VectorN-Impl.h:566
void ForEachIndex(Callback func) const
Iterates the vector and invoke given func for each index.
Definition: VectorN-Impl.h:552
VectorN()
Constructs empty vector.
Definition: VectorN-Impl.h:19
Base class for vector expression.
Definition: VectorExpression.h:28
Vector expression for unary operation.
Definition: VectorExpression.h:50
General purpose dynamically-sizedN-D vector class.
Definition: VectorN.h:27
1-D read-only array accessor class.
Definition: ArrayAccessor1.h:185
Vector expression for binary operation.
Definition: VectorExpression.h:85
void ParallelForEach(Callback func)
Iterates the vector and invoke given func for each element in parallel using multi-threading.
Definition: VectorN-Impl.h:559
Definition: pybind11Utils.h:24
ContainerType::iterator end()
Returns the end iterator of the vector.
Definition: VectorN-Impl.h:147
size_t size() const
Returns the size of the vector.
Definition: VectorN-Impl.h:117
size_t size() const
Size of the vector.
Definition: VectorExpression-Impl.h:18
constexpr size_t ZERO_SIZE
Zero size_t.
Definition: Constants.h:18
Point< T, 2 > Max(const Point< T, 2 > &a, const Point< T, 2 > &b)
Returns element-wise max point: (max(a.x, b.x), max(a.y, b.y)).
Definition: Point2-Impl.h:480
ContainerType::iterator begin()
Returns the begin iterator of the vector.
Definition: VectorN-Impl.h:135
1-D array accessor class.
Definition: ArrayAccessor1.h:28
T AbsMax(T x, T y)
Returns the absolute maximum value among the two inputs.
Definition: MathUtils-Impl.h:45
void ParallelFill(const RandomIterator &begin, const RandomIterator &end, const T &value, ExecutionPolicy policy)
Fills from begin to end with value in parallel.
Definition: Parallel-Impl.h:182
Point< T, 2 > Min(const Point< T, 2 > &a, const Point< T, 2 > &b)
Returns element-wise min point: (min(a.x, b.x), min(a.y, b.y)).
Definition: Point2-Impl.h:474
Value ParallelReduce(IndexType beginIndex, IndexType endIndex, const Value &identity, const Function &function, const Reduce &reduce, ExecutionPolicy policy)
Performs reduce operation in parallel.
Definition: Parallel-Impl.h:407
Vector expression for matrix-scalar binary operation.
Definition: VectorExpression.h:114