vmmlib  1.13.0
Templatized C++ vector and matrix math library
vector.hpp
1 /*
2  * Copyright (c) 2006-2016, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef __VMML__VECTOR__HPP__
34 #define __VMML__VECTOR__HPP__
35 
36 #include <algorithm>
37 #include <cmath>
38 #include <cstring>
39 #include <iomanip>
40 #include <iostream>
41 #include <limits>
42 #include <stdexcept>
43 #include <stdint.h>
44 #include <string>
45 #include <type_traits>
46 #include <vector>
47 
48 namespace vmml
49 {
50 template <size_t M, typename T>
51 class vector
52 {
53 public:
54  typedef T value_type;
55  typedef T* iterator;
56  typedef const T* const_iterator;
57  typedef std::reverse_iterator<iterator> reverse_iterator;
58  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
59 
60  static const size_t DIMENSION = M;
61 
62  // constructors
63  vector()
64  : array()
65  {
66  } // http://stackoverflow.com/questions/5602030
67  explicit vector(const T& a); // sets all components to a;
68  vector(const T& x, const T& y);
69  vector(const T& x, const T& y, const T& z);
70  vector(const T& x, const T& y, const T& z, const T& w);
71 
72 #ifndef SWIG
73  // initializes the first M-1 values from vector_, the last from last_
74  template <typename TT>
75  vector(const vector<M - 1, TT>& vector_, T last_,
76  typename std::enable_if<M == 4, TT>::type* = nullptr);
77 #endif
78 
79  explicit vector(const T* values);
80 
81 #ifdef __OSG_MATH
82  template <typename OSGVEC3>
83  explicit vector(const OSGVEC3& from,
84  typename std::enable_if<M == 3, OSGVEC3>::type* = nullptr);
85 #endif
86 
87  // vec< M > with homogeneous coordinates <-> vec< M-1 > conversion ctor
88  // to-homogenous-coordinates ctor
89  template <typename TT>
90  vector(const vector<3, TT>& source_,
91  typename std::enable_if<M == 4, TT>::type* = nullptr);
92 
93  // from-homogenous-coordinates vector
94  template <typename TT>
95  vector(const vector<4, TT>& source_,
96  typename std::enable_if<M == 3, TT>::type* = nullptr);
97 
98  template <typename U>
99  vector(const vector<M, U>& source_);
100 
101  // iterators
102  inline iterator begin();
103  inline iterator end();
104  inline const_iterator begin() const;
105  inline const_iterator end() const;
106  inline reverse_iterator rbegin();
107  inline reverse_iterator rend();
108  inline const_reverse_iterator rbegin() const;
109  inline const_reverse_iterator rend() const;
110 
111  // conversion operators
112  inline operator T*();
113  inline operator const T*() const;
114  // accessors
115  inline T& operator()(size_t index);
116  inline const T& operator()(size_t index) const;
117 
118  inline T& at(size_t index);
119  inline const T& at(size_t index) const;
120 
121  // element accessors for M <= 4;
122  inline T& x();
123  inline T& y();
124  inline T& z();
125  inline T& w();
126  inline const T& x() const;
127  inline const T& y() const;
128  inline const T& z() const;
129  inline const T& w() const;
130 
131  // pixel color element accessors for M<= 4
132  inline T& r();
133  inline T& g();
134  inline T& b();
135  inline T& a();
136  inline const T& r() const;
137  inline const T& g() const;
138  inline const T& b() const;
139  inline const T& a() const;
140 
141  bool operator==(const vector& other) const;
142  bool operator!=(const vector& other) const;
143  bool equals(const vector& other,
144  T tolerance = std::numeric_limits<T>::epsilon()) const;
145  bool operator<(const vector& other) const;
146 
147  // remember kids: c_arrays are dangerous and evil!
148  T operator=(T filler);
149 
150  vector& operator=(const vector& other);
151 
152  // returns void to avoid 'silent' loss of precision when chaining
153  template <typename U>
154  void operator=(const vector<M, U>& other);
155 
156  vector operator*(const vector& other) const;
157  vector operator/(const vector& other) const;
158  vector operator+(const vector& other) const;
159  vector operator-(const vector& other) const;
160 
161  void operator*=(const vector& other);
162  void operator/=(const vector& other);
163  void operator+=(const vector& other);
164  void operator-=(const vector& other);
165 
166  vector operator*(const T other) const;
167  vector operator/(const T other) const;
168  vector operator+(const T other) const;
169  vector operator-(const T other) const;
170 
171  void operator*=(const T other);
172  void operator/=(const T other);
173  void operator+=(const T other);
174  void operator-=(const T other);
175 
176  vector operator-() const;
177 
178  const vector& negate();
179 
180  void set(T a); // sets all components to a;
181  template <size_t N>
182  void set(const vector<N, T>& v);
183 
184  // sets the first few components to a certain value
185  void set(T x, T y);
186  void set(T x, T y, T z);
187  void set(T x, T y, T z, T w);
188 
189  template <typename input_iterator_t>
190  void iter_set(input_iterator_t begin_, input_iterator_t end_);
191 
192  // compute the cross product of two vectors
193  // note: there's also a free function:
194  // vector<> cross( const vector<>, const vector<> )
195  template <typename TT>
196  vector<M, T>& cross(const vector<M, TT>& b,
197  typename std::enable_if<M == 3, TT>::type* = nullptr);
198 
199  // compute the dot product of two vectors
200  // note: there's also a free function:
201  // T dot( const vector<>, const vector<> );
202  inline T dot(const vector& other) const;
203 
204  // normalize the vector
205  // note: there's also a free function:
206  // vector<> normalize( const vector<> );
207  inline T normalize();
208 
209  // sets all vector components to random values
210  // remember to set srand( seed );
211  // if seed is set to -1, srand( seed ) was set outside set_random
212  // otherwise srand( seed ) will be called with the given seed
213  void set_random(int seed = -1);
214 
215  inline T length() const;
216  inline T squared_length() const;
217 
218  inline T distance(const vector& other) const;
219  inline T squared_distance(const vector& other) const;
220 
222  T product() const;
223 
224  template <typename TT>
225  vector<3, T>& rotate(T theta, vector<M, TT> axis,
226  typename std::enable_if<M == 3, TT>::type* = nullptr);
227 
229  template <size_t N, size_t O>
230  vector<N, T> get_sub_vector(
231  typename std::enable_if<M >= N + O>::type* = nullptr) const;
232 
234  template <size_t N, size_t O>
235  void set_sub_vector(const vector<N, T>& sub,
236  typename std::enable_if<M >= N + O>::type* = nullptr);
237 
238  // sphere functions - sphere layout: center xyz, radius w
239  template <typename TT>
240  inline vector<3, T> project_point_onto_sphere(
241  const vector<3, TT>& point,
242  typename std::enable_if<M == 4, TT>::type* = nullptr) const;
243 
244  // returns a negative distance if the point lies in the sphere
245  template <typename TT>
246  inline T distance_to_sphere(
247  const vector<3, TT>& point,
248  typename std::enable_if<M == 4, TT>::type* = nullptr) const;
249 
250  // plane functions - plane layout; normal xyz, distance w
251  template <typename TT>
252  inline T distance_to_plane(
253  const vector<3, TT>& point,
254  typename std::enable_if<M == 4, TT>::type* = nullptr) const;
255 
256  template <typename TT>
257  inline vector<3, T> project_point_onto_plane(
258  const vector<3, TT>& point,
259  typename std::enable_if<M == 4, TT>::type* = nullptr) const;
260 
261  // returns the index of the minimal resp. maximal value in the vector
262  size_t find_min_index() const;
263  size_t find_max_index() const;
264 
265  // returns minimal resp. maximal value in the vector
266  T& find_min();
267  T& find_max();
268  const T& find_min() const;
269  const T& find_max() const;
270 
271  void clamp(const T& min = 0.0, const T& max = 1.0);
272 
273  inline static size_t size(); // returns M
274 
275  bool is_unit_vector() const;
276 
277  // perturbs each component by randomly + or - the perturbation parameter
278  void perturb(T perturbation = 0.0001);
279 
280  void sqrt_elementwise();
281  double norm() const; // l2 norm
282 
283  // computes the reciprocal value for each component, x = 1/x;
284  // WARNING: might result in nans if division by 0!
285  void reciprocal();
286  // computes the reciprocal value for each component, x = 1/x;
287  // checks every component for 0, sets to max value if zero.
288  void reciprocal_safe();
289 
290  template <typename TT>
291  void cast_from(const vector<M, TT>& other);
292 
293  size_t nnz() const;
294 
295  friend std::ostream& operator<<(std::ostream& os, const vector& vector_)
296  {
297  os << "[ ";
298  for (size_t index = 0; index < M; ++index)
299  os << vector_.at(index) << " ";
300  return os << "]";
301  }
302 
305  static vector<M, T> zero();
306  static vector<M, T> forward();
307  static vector<M, T> backward();
308  static vector<M, T> up();
309  static vector<M, T> down();
310  static vector<M, T> left();
311  static vector<M, T> right();
312  static vector<M, T> unitX();
313  static vector<M, T> unitY();
314  static vector<M, T> unitZ();
316 
317  T array[M];
318 };
319 
320 //
321 // some free functions for convenience
322 //
323 
324 template <size_t M, typename T>
325 bool equals(const vector<M, T>& a, const vector<M, T>& b)
326 {
327  return a.equals(b);
328 }
329 
330 // allows float * vector, not only vector * float
331 template <size_t M, typename T>
332 static vector<M, T> operator*(T factor, const vector<M, T>& vector_)
333 {
334  return vector_ * factor;
335 }
336 
337 template <size_t M, typename T>
338 inline T dot(const vector<M, T>& first, const vector<M, T>& second)
339 {
340  return first.dot(second);
341 }
342 
343 template <size_t M, typename T>
344 inline vector<M, T> cross(vector<M, T> a, const vector<M, T>& b)
345 {
346  return a.cross(b);
347 }
348 
349 template <size_t M, typename T>
350 vector<M, T> compute_normal(const vector<M, T>& a, const vector<M, T>& b,
351  const vector<M, T>& c)
352 {
353  // right hand system, CCW triangle
354  const vector<M, T> u = b - a;
355  const vector<M, T> v = c - a;
356  vector<M, T> w = cross(u, v);
357  w.normalize();
358  return w;
359 }
360 
361 template <typename T>
362 vector<3, T> rotate(vector<3, T> vec, const T theta, const vector<3, T>& axis)
363 {
364  return vec.rotate(theta, axis);
365 }
366 
367 template <size_t M, typename T>
368 inline vector<M, T> normalize(vector<M, T> vector_)
369 {
370  vector_.normalize();
371  return vector_;
372 }
373 
374 template <typename T>
375 inline vector<4, T> compute_plane(const vector<3, T>& a, const vector<3, T>& b,
376  const vector<3, T>& c)
377 {
378  const vector<3, T> cb = b - c;
379  const vector<3, T> ba = a - b;
380 
381  vector<4, T> plane = vector<4, T>(cross(cb, ba));
382  plane.normalize();
383  plane.w() = -plane.x() * a.x() - plane.y() * a.y() - plane.z() * a.z();
384  return plane;
385 }
386 
387 template <size_t M, typename T>
388 vector<M, T>::vector(const T& _a)
389 {
390  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
391  {
392  *it = _a;
393  }
394 }
395 
396 template <size_t M, typename T>
397 vector<M, T>::vector(const T& _x, const T& _y)
398 {
399  array[0] = _x;
400  array[1] = _y;
401 }
402 
403 template <size_t M, typename T>
404 vector<M, T>::vector(const T& _x, const T& _y, const T& _z)
405 {
406  array[0] = _x;
407  array[1] = _y;
408  array[2] = _z;
409 }
410 
411 template <size_t M, typename T>
412 vector<M, T>::vector(const T& _x, const T& _y, const T& _z, const T& _w)
413 {
414  array[0] = _x;
415  array[1] = _y;
416  array[2] = _z;
417  array[3] = _w;
418 }
419 
420 template <size_t M, typename T>
421 vector<M, T>::vector(const T* values)
422 {
423  memcpy(array, values, M * sizeof(T));
424 }
425 
426 #ifdef __OSG_MATH
427 template <size_t M, typename T>
428 template <typename OSGVEC3>
429 vector<M, T>::vector(const OSGVEC3& from,
430  typename std::enable_if<M == 3, OSGVEC3>::type*)
431 {
432  array[0] = from.x();
433  array[1] = from.y();
434  array[2] = from.z();
435 }
436 #endif
437 
438 #ifndef SWIG
439 template <size_t M, typename T>
440 template <typename TT>
441 // initializes the first M-1 values from vector_, the last from last_
442 vector<M, T>::vector(const vector<M - 1, TT>& vector_, T last_,
443  typename std::enable_if<M == 4, TT>::type*)
444 {
445  array[0] = vector_.array[0];
446  array[1] = vector_.array[1];
447  array[2] = vector_.array[2];
448  array[3] = last_;
449 }
450 #endif
451 
452 // to-homogenous-coordinates ctor
453 template <size_t M, typename T>
454 template <typename TT>
455 vector<M, T>::vector(const vector<3, TT>& source_,
456  typename std::enable_if<M == 4, TT>::type*)
457 {
458  std::copy(source_.begin(), source_.end(), begin());
459  at(M - 1) = static_cast<T>(1.0);
460 }
461 
462 // from-homogenous-coordinates ctor
463 template <size_t M, typename T>
464 template <typename TT>
465 vector<M, T>::vector(const vector<4, TT>& source_,
466  typename std::enable_if<M == 3, TT>::type*)
467 {
468  const T w_reci = static_cast<T>(1.0) / source_(M);
469  iterator it = begin(), it_end = end();
470  for (size_t index = 0; it != it_end; ++it, ++index)
471  *it = source_(index) * w_reci;
472 }
473 
474 template <size_t M, typename T>
475 template <typename U>
476 vector<M, T>::vector(const vector<M, U>& source_)
477 {
478  (*this) = source_;
479 }
480 
481 namespace
482 {
483 template <size_t M, typename T>
484 vector<M, T> _createVector(const T x, const T y, const T z,
485  typename std::enable_if<M == 3>::type* = nullptr)
486 {
487  return vector<M, T>(x, y, z);
488 }
489 
490 template <size_t M, typename T>
491 vector<M, T> _createVector(const T x, const T y, const T z,
492  typename std::enable_if<M == 4>::type* = nullptr)
493 {
494  return vector<M, T>(x, y, z, 1);
495 }
496 }
497 
498 template <size_t M, typename T>
500 {
501  return _createVector<M, T>(0, 0, 0);
502 }
503 
504 template <size_t M, typename T>
506 {
507  return _createVector<M, T>(0, 0, -1);
508 }
509 
510 template <size_t M, typename T>
512 {
513  return _createVector<M, T>(0, 0, 1);
514 }
515 
516 template <size_t M, typename T>
518 {
519  return _createVector<M, T>(0, 1, 0);
520 }
521 
522 template <size_t M, typename T>
524 {
525  return _createVector<M, T>(0, -1, 0);
526 }
527 
528 template <size_t M, typename T>
530 {
531  return _createVector<M, T>(-1, 0, 0);
532 }
533 
534 template <size_t M, typename T>
536 {
537  return _createVector<M, T>(1, 0, 0);
538 }
539 
540 template <size_t M, typename T>
542 {
543  return _createVector<M, T>(1, 0, 0);
544 }
545 
546 template <size_t M, typename T>
548 {
549  return _createVector<M, T>(0, 1, 0);
550 }
551 
552 template <size_t M, typename T>
554 {
555  return _createVector<M, T>(0, 0, 1);
556 }
557 
558 template <size_t M, typename T>
559 void vector<M, T>::set(T _a)
560 {
561  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
562  *it = _a;
563 }
564 
565 template <size_t M, typename T>
566 template <size_t N>
567 void vector<M, T>::set(const vector<N, T>& v)
568 {
569  size_t minimum = M;
570  if (N < M)
571  minimum = N;
572  memcpy(array, v.array, sizeof(T) * minimum);
573 }
574 
575 template <size_t M, typename T>
576 void vector<M, T>::set(T _x, T _y)
577 {
578  array[0] = _x;
579  array[1] = _y;
580 }
581 
582 template <size_t M, typename T>
583 void vector<M, T>::set(T _x, T _y, T _z)
584 {
585  array[0] = _x;
586  array[1] = _y;
587  array[2] = _z;
588 }
589 
590 template <size_t M, typename T>
591 void vector<M, T>::set(T _x, T _y, T _z, T _w)
592 {
593  array[0] = _x;
594  array[1] = _y;
595  array[2] = _z;
596  array[3] = _w;
597 }
598 
599 template <size_t M, typename T>
600 inline T& vector<M, T>::operator()(size_t index)
601 {
602  return at(index);
603 }
604 
605 template <size_t M, typename T>
606 inline const T& vector<M, T>::operator()(size_t index) const
607 {
608  return at(index);
609 }
610 
611 template <size_t M, typename T>
612 inline T& vector<M, T>::at(size_t index)
613 {
614  if (index >= M)
615  throw std::runtime_error("at() - index out of bounds");
616  return array[index];
617 }
618 
619 template <size_t M, typename T>
620 inline const T& vector<M, T>::at(size_t index) const
621 {
622  if (index >= M)
623  throw std::runtime_error("at() - index out of bounds");
624  return array[index];
625 }
626 
627 template <size_t M, typename T>
629 {
630  return array;
631 }
632 
633 template <size_t M, typename T>
634 vector<M, T>::operator const T*() const
635 {
636  return array;
637 }
638 
639 template <size_t M, typename T>
641 {
642  vector<M, T> result;
643  for (size_t index = 0; index < M; ++index)
644  result.at(index) = at(index) * other.at(index);
645  return result;
646 }
647 
648 template <size_t M, typename T>
650 {
651  vector<M, T> result;
652  for (size_t index = 0; index < M; ++index)
653  result.at(index) = at(index) / other.at(index);
654  return result;
655 }
656 
657 template <size_t M, typename T>
659 {
660  vector<M, T> result;
661  for (size_t index = 0; index < M; ++index)
662  result.at(index) = at(index) + other.at(index);
663  return result;
664 }
665 
666 template <size_t M, typename T>
668 {
669  vector<M, T> result;
670  for (size_t index = 0; index < M; ++index)
671  result.at(index) = at(index) - other.at(index);
672  return result;
673 }
674 
675 template <size_t M, typename T>
676 void vector<M, T>::operator*=(const vector<M, T>& other)
677 {
678  for (size_t index = 0; index < M; ++index)
679  at(index) *= other.at(index);
680 }
681 
682 template <size_t M, typename T>
683 void vector<M, T>::operator/=(const vector<M, T>& other)
684 {
685  for (size_t index = 0; index < M; ++index)
686  at(index) /= other.at(index);
687 }
688 
689 template <size_t M, typename T>
690 void vector<M, T>::operator+=(const vector<M, T>& other)
691 {
692  for (size_t index = 0; index < M; ++index)
693  at(index) += other.at(index);
694 }
695 
696 template <size_t M, typename T>
697 void vector<M, T>::operator-=(const vector<M, T>& other)
698 {
699  for (size_t index = 0; index < M; ++index)
700  at(index) -= other.at(index);
701 }
702 
703 template <size_t M, typename T>
704 vector<M, T> vector<M, T>::operator*(const T other) const
705 {
706  vector<M, T> result;
707  for (size_t index = 0; index < M; ++index)
708  result.at(index) = at(index) * other;
709  return result;
710 }
711 
712 template <size_t M, typename T>
713 vector<M, T> vector<M, T>::operator/(const T other) const
714 {
715  vector<M, T> result;
716  for (size_t index = 0; index < M; ++index)
717  result.at(index) = at(index) / other;
718  return result;
719 }
720 
721 template <size_t M, typename T>
722 vector<M, T> vector<M, T>::operator+(const T other) const
723 {
724  vector<M, T> result;
725  for (size_t index = 0; index < M; ++index)
726  result.at(index) = at(index) + other;
727  return result;
728 }
729 
730 template <size_t M, typename T>
731 vector<M, T> vector<M, T>::operator-(const T other) const
732 {
733  vector<M, T> result;
734  for (size_t index = 0; index < M; ++index)
735  result.at(index) = at(index) - other;
736  return result;
737 }
738 
739 template <size_t M, typename T>
740 void vector<M, T>::operator*=(const T other)
741 {
742  for (size_t index = 0; index < M; ++index)
743  at(index) *= other;
744 }
745 
746 template <size_t M, typename T>
747 void vector<M, T>::operator/=(const T other)
748 {
749  for (size_t index = 0; index < M; ++index)
750  at(index) /= other;
751 }
752 
753 template <size_t M, typename T>
754 void vector<M, T>::operator+=(const T other)
755 {
756  for (size_t index = 0; index < M; ++index)
757  at(index) += other;
758 }
759 
760 template <size_t M, typename T>
761 void vector<M, T>::operator-=(const T other)
762 {
763  for (size_t index = 0; index < M; ++index)
764  at(index) -= other;
765 }
766 
767 template <size_t M, typename T>
769 {
770  vector<M, T> v(*this);
771  return v.negate();
772 }
773 
774 template <size_t M, typename T>
776 {
777  for (size_t index = 0; index < M; ++index)
778  array[index] = -array[index];
779  return *this;
780 }
781 
782 template <size_t M, typename T>
783 inline T& vector<M, T>::x()
784 {
785  return array[0];
786 }
787 
788 template <size_t M, typename T>
789 inline T& vector<M, T>::y()
790 {
791  return array[1];
792 }
793 
794 template <size_t M, typename T>
795 inline T& vector<M, T>::z()
796 {
797  return array[2];
798 }
799 
800 template <size_t M, typename T>
801 inline T& vector<M, T>::w()
802 {
803  return array[3];
804 }
805 
806 template <size_t M, typename T>
807 inline const T& vector<M, T>::x() const
808 {
809  return array[0];
810 }
811 
812 template <size_t M, typename T>
813 inline const T& vector<M, T>::y() const
814 {
815  return array[1];
816 }
817 
818 template <size_t M, typename T>
819 inline const T& vector<M, T>::z() const
820 {
821  return array[2];
822 }
823 
824 template <size_t M, typename T>
825 inline const T& vector<M, T>::w() const
826 {
827  return array[3];
828 }
829 
830 template <size_t M, typename T>
831 inline T& vector<M, T>::r()
832 {
833  return array[0];
834 }
835 
836 template <size_t M, typename T>
837 inline T& vector<M, T>::g()
838 {
839  return array[1];
840 }
841 
842 template <size_t M, typename T>
843 inline T& vector<M, T>::b()
844 {
845  return array[2];
846 }
847 
848 template <size_t M, typename T>
849 inline T& vector<M, T>::a()
850 {
851  return array[3];
852 }
853 
854 template <size_t M, typename T>
855 inline const T& vector<M, T>::r() const
856 {
857  return array[0];
858 }
859 
860 template <size_t M, typename T>
861 inline const T& vector<M, T>::g() const
862 {
863  return array[1];
864 }
865 
866 template <size_t M, typename T>
867 inline const T& vector<M, T>::b() const
868 {
869  return array[2];
870 }
871 
872 template <size_t M, typename T>
873 inline const T& vector<M, T>::a() const
874 {
875  return array[3];
876 }
877 
878 template <size_t M, typename T>
879 template <typename TT>
881  typename std::enable_if<M == 3, TT>::type*)
882 {
883  const T x_ = y() * rhs.z() - z() * rhs.y();
884  const T y_ = z() * rhs.x() - x() * rhs.z();
885  const T z_ = x() * rhs.y() - y() * rhs.x();
886  x() = x_;
887  y() = y_;
888  z() = z_;
889  return *this;
890 }
891 
892 template <size_t M, typename T>
893 inline T vector<M, T>::dot(const vector<M, T>& other) const
894 {
895  T tmp = 0.0;
896  for (size_t index = 0; index < M; ++index)
897  tmp += at(index) * other.at(index);
898 
899  return tmp;
900 }
901 
902 template <size_t M, typename T>
903 inline T vector<M, T>::normalize()
904 {
905  const T len = length();
906  if (len <= std::numeric_limits<T>::epsilon())
907  return 0;
908 
909  const T tmp = 1.0 / len;
910  (*this) *= tmp;
911  return len;
912 }
913 
914 template <size_t M, typename T>
915 inline T vector<M, T>::length() const
916 {
917  return std::sqrt(squared_length());
918 }
919 
920 template <size_t M, typename T>
921 inline T vector<M, T>::squared_length() const
922 {
923  T _squared_length = 0.0;
924  for (const_iterator it = begin(), it_end = end(); it != it_end; ++it)
925  _squared_length += (*it) * (*it);
926 
927  return _squared_length;
928 }
929 
930 template <size_t M, typename T>
931 inline T vector<M, T>::distance(const vector<M, T>& other) const
932 {
933  return std::sqrt(squared_distance(other));
934 }
935 
936 template <size_t M, typename T>
937 inline T vector<M, T>::squared_distance(const vector<M, T>& other) const
938 {
939  vector<M, T> tmp(*this);
940  tmp -= other;
941  return tmp.squared_length();
942 }
943 
944 template <size_t M, typename T>
945 inline T vector<M, T>::product() const
946 {
947  T result = at(0);
948  for (size_t i = 1; i < M; ++i)
949  result *= at(i);
950  return result;
951 }
952 
953 template <size_t M, typename T>
954 template <typename TT>
955 vector<3, T>& vector<M, T>::rotate(const T theta, vector<M, TT> axis,
956  typename std::enable_if<M == 3, TT>::type*)
957 {
958  const T costheta = std::cos(theta);
959  const T sintheta = std::sin(theta);
960 
961  axis.normalize();
962  return *this = vector<3, T>(
963  (costheta + (1 - costheta) * axis.x() * axis.x()) * x() +
964  ((1 - costheta) * axis.x() * axis.y() -
965  axis.z() * sintheta) *
966  y() +
967  ((1 - costheta) * axis.x() * axis.z() +
968  axis.y() * sintheta) *
969  z(),
970 
971  ((1 - costheta) * axis.x() * axis.y() + axis.z() * sintheta) *
972  x() +
973  (costheta + (1 - costheta) * axis.y() * axis.y()) * y() +
974  ((1 - costheta) * axis.y() * axis.z() -
975  axis.x() * sintheta) *
976  z(),
977 
978  ((1 - costheta) * axis.x() * axis.z() - axis.y() * sintheta) *
979  x() +
980  ((1 - costheta) * axis.y() * axis.z() +
981  axis.x() * sintheta) *
982  y() +
983  (costheta + (1 - costheta) * axis.z() * axis.z()) * z());
984 }
985 
986 // sphere layout: center xyz, radius w
987 template <size_t M, typename T>
988 template <typename TT>
990  const vector<3, TT>& point,
991  typename std::enable_if<M == 4, TT>::type*) const
992 {
993  const vector<3, T>& center_ = get_sub_vector<3>();
994 
995  vector<3, T> projected_point(point);
996  projected_point -= center_;
997  projected_point.normalize();
998  projected_point *= w();
999  return center_ + projected_point;
1000 }
1001 
1002 // sphere layout: center xyz, radius w
1003 template <size_t M, typename T>
1004 template <typename TT>
1006  const vector<3, TT>& point,
1007  typename std::enable_if<M == 4, TT>::type*) const
1008 {
1009  const vector<3, T>& center_ = get_sub_vector<3>();
1010  return (point - center_).length() - w();
1011 }
1012 
1013 template <size_t M, typename T>
1014 template <size_t N, size_t O>
1016  typename std::enable_if<M >= N + O>::type*) const
1017 {
1018  return vector<N, T>(array + O);
1019 }
1020 
1021 template <size_t M, typename T>
1022 template <size_t N, size_t O>
1024  typename std::enable_if<M >= N + O>::type*)
1025 {
1026  ::memcpy(array + O, sub.array, N * sizeof(T));
1027 }
1028 
1029 // plane: normal xyz, distance w
1030 template <size_t M, typename T>
1031 template <typename TT>
1033  const vector<3, TT>& point,
1034  typename std::enable_if<M == 4, TT>::type*) const
1035 {
1036  const vector<3, T>& normal = get_sub_vector<3>();
1037  return normal.dot(point) + w();
1038 }
1039 
1040 // plane: normal xyz, distance w
1041 template <size_t M, typename T>
1042 template <typename TT>
1044  const vector<3, TT>& point,
1045  typename std::enable_if<M == 4, TT>::type*) const
1046 {
1047  const vector<3, T>& normal = get_sub_vector<3>();
1048  return point - (normal * distance_to_plane(point));
1049 }
1050 
1051 template <size_t M, typename T>
1052 bool vector<M, T>::operator==(const vector<M, T>& other) const
1053 {
1054  return memcmp(array, other.array, sizeof(array)) == 0;
1055 }
1056 
1057 template <size_t M, typename T>
1058 bool vector<M, T>::operator!=(const vector<M, T>& other) const
1059 {
1060  return !this->operator==(other);
1061 }
1062 
1063 template <size_t M, typename T>
1064 bool vector<M, T>::equals(const vector<M, T>& other, T tolerance) const
1065 {
1066  for (size_t index = 0; index < M; ++index)
1067  if (fabs(at(index) - other(index)) >= tolerance)
1068  return false;
1069  return true;
1070 }
1071 
1072 template <size_t M, typename T>
1073 bool vector<M, T>::operator<(const vector<M, T>& other) const
1074 {
1075  for (size_t index = 0; index < M; ++index)
1076  {
1077  if (at(index) < other.at(index))
1078  return true;
1079  if (other.at(index) < at(index))
1080  return false;
1081  }
1082  return false;
1083 }
1084 
1085 template <size_t M, typename T>
1086 T vector<M, T>::operator=(T filler_value)
1087 {
1088  for (size_t index = 0; index < M; ++index)
1089  at(index) = filler_value;
1090  return filler_value;
1091 }
1092 
1093 template <size_t M, typename T>
1095 {
1096  if (this != &other)
1097  memcpy(array, other.array, M * sizeof(T));
1098  return *this;
1099 }
1100 
1101 // returns void to avoid 'silent' loss of precision when chaining
1102 template <size_t M, typename T>
1103 template <typename U>
1104 void vector<M, T>::operator=(const vector<M, U>& source_)
1105 {
1106  typedef typename vector<M, U>::const_iterator u_c_iter;
1107  u_c_iter it = source_.begin(), it_end = source_.end();
1108  for (iterator my_it = begin(); it != it_end; ++it, ++my_it)
1109  *my_it = static_cast<T>(*it);
1110 }
1111 
1112 template <size_t M, typename T>
1113 template <typename input_iterator_t>
1114 void vector<M, T>::iter_set(input_iterator_t begin_, input_iterator_t end_)
1115 {
1116  input_iterator_t in_it = begin_;
1117  iterator it = begin(), it_end = end();
1118  for (; it != it_end && in_it != end_; ++it, ++in_it)
1119  (*it) = static_cast<T>(*in_it);
1120 }
1121 
1122 template <size_t M, typename T>
1123 void vector<M, T>::clamp(const T& min, const T& max)
1124 {
1125  for (size_t i = 0; i < M; ++i)
1126  {
1127  if (array[i] < min)
1128  array[i] = min;
1129  if (array[i] > max)
1130  array[i] = max;
1131  }
1132 }
1133 
1134 template <size_t M, typename T>
1135 inline size_t vector<M, T>::size()
1136 {
1137  return M;
1138 }
1139 
1140 template <size_t M, typename T>
1141 size_t vector<M, T>::find_min_index() const
1142 {
1143  return std::min_element(begin(), end()) - begin();
1144 }
1145 
1146 template <size_t M, typename T>
1147 size_t vector<M, T>::find_max_index() const
1148 {
1149  return std::max_element(begin(), end()) - begin();
1150 }
1151 
1152 template <size_t M, typename T>
1154 {
1155  return *std::min_element(begin(), end());
1156 }
1157 
1158 template <size_t M, typename T>
1159 const T& vector<M, T>::find_min() const
1160 {
1161  return *std::min_element(begin(), end());
1162 }
1163 
1164 template <size_t M, typename T>
1166 {
1167  return *std::max_element(begin(), end());
1168 }
1169 
1170 template <size_t M, typename T>
1171 const T& vector<M, T>::find_max() const
1172 {
1173  return *std::max_element(begin(), end());
1174 }
1175 
1176 template <size_t M, typename T>
1177 inline typename vector<M, T>::iterator vector<M, T>::begin()
1178 {
1179  return array;
1180 }
1181 
1182 template <size_t M, typename T>
1183 inline typename vector<M, T>::iterator vector<M, T>::end()
1184 {
1185  return array + M;
1186  ;
1187 }
1188 
1189 template <size_t M, typename T>
1190 inline typename vector<M, T>::const_iterator vector<M, T>::begin() const
1191 {
1192  return array;
1193 }
1194 
1195 template <size_t M, typename T>
1196 inline typename vector<M, T>::const_iterator vector<M, T>::end() const
1197 {
1198  return array + M;
1199  ;
1200 }
1201 
1202 template <size_t M, typename T>
1203 inline typename vector<M, T>::reverse_iterator vector<M, T>::rbegin()
1204 {
1205  return array + M - 1;
1206 }
1207 
1208 template <size_t M, typename T>
1209 inline typename vector<M, T>::reverse_iterator vector<M, T>::rend()
1210 {
1211  return array - 1;
1212 }
1213 
1214 template <size_t M, typename T>
1215 inline typename vector<M, T>::const_reverse_iterator vector<M, T>::rbegin()
1216  const
1217 {
1218  return array + M - 1;
1219 }
1220 
1221 template <size_t M, typename T>
1222 inline typename vector<M, T>::const_reverse_iterator vector<M, T>::rend() const
1223 {
1224  return array - 1;
1225 }
1226 
1227 template <size_t M, typename T>
1228 bool vector<M, T>::is_unit_vector() const
1229 {
1230  const_iterator it = begin(), it_end = end();
1231  bool one = false;
1232  for (; it != it_end; ++it)
1233  {
1234  if (*it == 1.0)
1235  {
1236  if (one)
1237  return false;
1238  one = true;
1239  }
1240  else if (*it != 0.0)
1241  {
1242  return false;
1243  }
1244  }
1245  return one;
1246 }
1247 
1248 template <size_t M, typename T>
1249 void vector<M, T>::perturb(T perturbation)
1250 {
1251  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
1252  {
1253  (*it) += (rand() & 1u) ? perturbation : -perturbation;
1254  }
1255 }
1256 
1257 template <size_t M, typename T>
1259 {
1260  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
1261  {
1262  (*it) = std::sqrt(*it);
1263  }
1264 }
1265 
1266 template <size_t M, typename T>
1268 {
1269  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
1270  (*it) = static_cast<T>(1) / (*it);
1271 }
1272 
1273 template <size_t M, typename T>
1275 {
1276  for (iterator it = begin(), it_end = end(); it != it_end; ++it)
1277  {
1278  T& v = *it;
1279 
1280  if (v == 0)
1281  v = std::numeric_limits<T>::max();
1282  else
1283  v = static_cast<T>(1) / v;
1284  }
1285 }
1286 
1287 template <size_t M, typename T>
1288 template <typename TT>
1289 void vector<M, T>::cast_from(const vector<M, TT>& other)
1290 {
1291  typedef vmml::vector<M, TT> vector_tt_type;
1292  typedef typename vector_tt_type::const_iterator tt_const_iterator;
1293 
1294  iterator it = begin(), it_end = end();
1295  tt_const_iterator other_it = other.begin();
1296  for (; it != it_end; ++it, ++other_it)
1297  {
1298  *it = static_cast<T>(*other_it);
1299  }
1300 }
1301 
1302 template <size_t M, typename T>
1303 size_t vector<M, T>::nnz() const
1304 {
1305  size_t counter = 0;
1306 
1307  const_iterator it = begin(), it_end = end();
1308  for (; it != it_end; ++it)
1309  {
1310  if (*it != 0)
1311  {
1312  ++counter;
1313  }
1314  }
1315 
1316  return counter;
1317 }
1318 
1319 template <size_t M, typename T>
1320 double vector<M, T>::norm() const
1321 {
1322  double norm_v = 0.0;
1323 
1324  const_iterator it = begin(), it_end = end();
1325  for (; it != it_end; ++it)
1326  {
1327  norm_v += *it * *it;
1328  }
1329 
1330  return std::sqrt(norm_v);
1331 }
1332 
1333 template <size_t M, typename T>
1334 void vector<M, T>::set_random(int seed)
1335 {
1336  if (seed >= 0)
1337  srand(seed);
1338 
1339  for (size_t i = 0; i < M; ++i)
1340  {
1341  const double fillValue = double(rand()) / double(RAND_MAX);
1342  at(i) = -1.0 + 2.0 * fillValue;
1343  }
1344 }
1345 
1346 } // namespace vmml
1347 
1348 #endif
Definition: aabb.hpp:44
void set_sub_vector(const vector< N, T > &sub, typename std::enable_if< M >=N+O >::type *=nullptr)
Set the sub vector of the given length at the given offset.
Definition: vector.hpp:1023
T array[M]
storage
Definition: vector.hpp:317
vector< N, T > get_sub_vector(typename std::enable_if< M >=N+O >::type *=nullptr) const
Definition: vector.hpp:1015
T product() const
Definition: vector.hpp:945