NVIDIA Iray: Math API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vector.h
Go to the documentation of this file.
1 //*****************************************************************************
2 // Copyright 1986, 2014 NVIDIA Corporation. All rights reserved.
3 //*****************************************************************************
9 //*****************************************************************************
10 
11 #ifndef MI_MATH_VECTOR_H
12 #define MI_MATH_VECTOR_H
13 
14 #include <mi/base/types.h>
15 #include <mi/math/assert.h>
16 #include <mi/math/function.h>
17 
18 namespace mi {
19 
20 namespace math {
21 
39 };
40 
41 
42 // Color and Vector can be converted into each other. To avoid cyclic dependencies among the
43 // headers, the Color_struct class is already defined here.
44 
45 //------- POD struct that provides storage for color elements --------
46 
67 struct Color_struct
68 {
77 };
78 
79 
106 //------- POD struct that provides storage for vector elements --------
107 
134 template <typename T, Size DIM>
136 {
137  T elements[DIM];
138 };
139 
141 template <typename T> struct Vector_struct<T, 1>
142 {
143  T x;
144 };
145 
147 template <typename T> struct Vector_struct<T, 2>
148 {
149  T x;
150  T y;
151 };
152 
154 template <typename T> struct Vector_struct<T, 3>
155 {
156  T x;
157  T y;
158  T z;
159 };
160 
162 template <typename T> struct Vector_struct<T, 4>
163 {
164  T x;
165  T y;
166  T z;
167  T w;
168 };
169 
170 
171 //------ Indirect access to vector storage base ptr to keep Vector_struct a POD --
172 
174 template <typename T, Size DIM>
176 {
177  return vec.elements;
178 }
179 
181 template <typename T, Size DIM>
182 inline const T* vector_base_ptr( const Vector_struct<T,DIM>& vec)
183 {
184  return vec.elements;
185 }
186 
188 template <typename T>
190 {
191  return &vec.x;
192 }
193 
195 template <typename T>
196 inline const T* vector_base_ptr( const Vector_struct<T,1>& vec)
197 {
198  return &vec.x;
199 }
200 
202 template <typename T>
204 {
205  return &vec.x;
206 }
207 
209 template <typename T>
210 inline const T* vector_base_ptr( const Vector_struct<T,2>& vec)
211 {
212  return &vec.x;
213 }
214 
216 template <typename T>
218 {
219  return &vec.x;
220 }
221 
223 template <typename T>
224 inline const T* vector_base_ptr( const Vector_struct<T,3>& vec)
225 {
226  return &vec.x;
227 }
228 
230 template <typename T>
232 {
233  return &vec.x;
234 }
235 
237 template <typename T>
238 inline const T* vector_base_ptr( const Vector_struct<T,4>& vec)
239 {
240  return &vec.x;
241 }
242 
243  // end group mi_math_vector_struct
245 
246 
247 //------ Generic Vector Class -------------------------------------------------
248 
249 template < class T, Size DIM>
250 class Vector;
251 // Using a proxy class to make comparison operators a lesser match when it comes
252 // to an overload resolution set with the MetaSL definitions of these operators.
253 template <typename T, Size DIM>
254 struct Vector_proxy_
255 {
256  const Vector<T,DIM>& vec;
257  Vector_proxy_( const Vector<T,DIM>& v) : vec( v) { }
258 };
259 
260 
261 
298 template < class T, Size DIM>
299 class Vector : public Vector_struct<T, DIM>
300 {
301 public:
304 
305  typedef T value_type;
306  typedef Size size_type;
308  typedef T * pointer;
309  typedef const T * const_pointer;
310  typedef T & reference;
311  typedef const T & const_reference;
312 
313  static const Size DIMENSION = DIM;
314  static const Size SIZE = DIM;
315 
317  static inline Size size() { return SIZE; }
318 
320  static inline Size max_size() { return SIZE; }
321 
323  inline T* begin() { return mi::math::vector_base_ptr( *this); }
324 
326  inline const T* begin() const { return mi::math::vector_base_ptr( *this); }
327 
331  inline T* end() { return begin() + DIM; }
332 
336  inline const T* end() const { return begin() + DIM; }
337 
339  inline Vector()
340  {
341 #if defined(DEBUG) || (defined(_MSC_VER) && _MSC_VER <= 1310)
342  // In debug mode, default-constructed vectors are initialized with signaling NaNs or, if not
343  // applicable, with a maximum value to increase the chances of diagnosing incorrect use of
344  // an uninitialized vector.
345  //
346  // When compiling with Visual C++ 7.1 or earlier, this code is enabled in all variants to
347  // work around a very obscure compiler bug that causes the compiler to crash.
348  typedef mi::base::numeric_traits<T> Traits;
349  T v = (Traits::has_signaling_NaN) ? Traits::signaling_NaN()
350  : Traits::max MI_PREVENT_MACRO_EXPAND ();
351  for( Size i(0u); i < DIM; ++i)
352  (*this)[i] = v;
353 #endif
354  }
355 
357  inline Vector( const Vector_struct<T,DIM>& vec )
358  {
359  for( Size i(0u); i < DIM; ++i)
360  (*this)[i] = mi::math::vector_base_ptr(vec)[i];
361  }
362 
364  inline explicit Vector(T v)
365  {
366  for( Size i(0u); i < DIM; ++i)
367  (*this)[i] = v;
368  }
369 
383  template <typename Iterator>
384  inline Vector(From_iterator_tag, Iterator p)
385  {
386  for( Size i(0u); i < DIM; ++i, ++p)
387  (*this)[i] = *p;
388  }
389 
401  template <typename T2>
402  inline explicit Vector( T2 const (& array)[DIM])
403  {
404  for( Size i(0u); i < DIM; ++i)
405  (*this)[i] = array[i];
406  }
407 
410  template <typename T2>
411  inline explicit Vector( const Vector<T2,DIM>& other)
412  {
413  for( Size i(0u); i < DIM; ++i)
414  (*this)[i] = T(other[i]);
415  }
416 
421  inline Vector(T v1, T v2)
422  {
423  mi_static_assert(DIM == 2);
424  begin()[0] = v1;
425  begin()[1] = v2;
426  }
427 
432  inline Vector(T v1, T v2, T v3)
433  {
434  mi_static_assert(DIM == 3);
435  begin()[0] = v1;
436  begin()[1] = v2;
437  begin()[2] = v3;
438  }
439 
444  inline Vector(T v1, const Vector<T,2>& v2)
445  {
446  mi_static_assert(DIM == 3);
447  begin()[0] = v1;
448  begin()[1] = v2.x;
449  begin()[2] = v2.y;
450  }
451 
456  inline Vector(const Vector<T,2>& v1, T v2)
457  {
458  mi_static_assert(DIM == 3);
459  begin()[0] = v1.x;
460  begin()[1] = v1.y;
461  begin()[2] = v2;
462  }
463 
468  inline Vector(T v1, T v2, T v3, T v4)
469  {
470  mi_static_assert(DIM == 4);
471  begin()[0] = v1;
472  begin()[1] = v2;
473  begin()[2] = v3;
474  begin()[3] = v4;
475  }
476 
481  inline Vector(T v1, T v2, const Vector<T,2>& v3)
482  {
483  mi_static_assert(DIM == 4);
484  begin()[0] = v1;
485  begin()[1] = v2;
486  begin()[2] = v3.x;
487  begin()[3] = v3.y;
488  }
489 
490 
495  inline Vector(T v1, const Vector<T,2>& v2, T v3)
496  {
497  mi_static_assert(DIM == 4);
498  begin()[0] = v1;
499  begin()[1] = v2.x;
500  begin()[2] = v2.y;
501  begin()[3] = v3;
502  }
503 
508  inline Vector(const Vector<T,2>& v1, T v2, T v3)
509  {
510  mi_static_assert(DIM == 4);
511  begin()[0] = v1.x;
512  begin()[1] = v1.y;
513  begin()[2] = v2;
514  begin()[3] = v3;
515  }
516 
521  inline Vector(const Vector<T,2>& v1, const Vector<T,2>& v2)
522  {
523  mi_static_assert(DIM == 4);
524  begin()[0] = v1.x;
525  begin()[1] = v1.y;
526  begin()[2] = v2.x;
527  begin()[3] = v2.y;
528  }
529 
534  inline Vector(T v1, const Vector<T,3>& v2)
535  {
536  mi_static_assert(DIM == 4);
537  begin()[0] = v1;
538  begin()[1] = v2.x;
539  begin()[2] = v2.y;
540  begin()[3] = v2.z;
541  }
542 
547  inline Vector(const Vector<T,3>& v1, T v2)
548  {
549  mi_static_assert(DIM == 4);
550  begin()[0] = v1.x;
551  begin()[1] = v1.y;
552  begin()[2] = v1.z;
553  begin()[3] = v2;
554  }
555 
560  inline explicit Vector( const Color_struct& color)
561  {
562  mi_static_assert(DIM == 4);
563  this->x = color.r;
564  this->y = color.g;
565  this->z = color.b;
566  this->w = color.a;
567  }
568 
570  inline Vector& operator= ( const Vector& other)
571  {
572  for( Size i(0u); i < DIM; ++i)
573  (*this)[i] = other[i];
574  return *this;
575  }
576 
578  inline Vector& operator= ( T s)
579  {
580  for( Size i(0u); i < DIM; ++i)
581  (*this)[i] = s;
582  return *this;
583  }
588  inline Vector& operator= ( const Color_struct& color)
589  {
590  mi_static_assert(DIM == 4);
591  this->x = color.r;
592  this->y = color.g;
593  this->z = color.b;
594  this->w = color.a;
595  return *this;
596  }
597 
601  inline T& operator[] (Size i)
602  {
603  mi_math_assert_msg(i < DIM, "precondition");
604  return begin()[i];
605  }
606 
610  inline const T& operator[] (Size i) const
611  {
612  mi_math_assert_msg(i < DIM, "precondition");
613  return begin()[i];
614  }
615 
619  inline const T& get(Size i) const
620  {
621  mi_math_assert_msg(i < DIM, "precondition");
622  return begin()[i];
623  }
624 
628  inline void set(Size i, T value)
629  {
630  mi_math_assert_msg(i < DIM, "precondition");
631  begin()[i] = value;
632  }
633 
634 
635 
642  inline bool normalize()
643  {
644  const T rec_length = T(1) / length( *this);
645  const bool result = isfinite( rec_length);
646  if( result)
647  (*this) *= rec_length;
648  return result;
649  }
650 
651 
652  //------ Free comparison operators ==, !=, <, <=, >, >= for vectors --------
653  // Using a proxy class to make comparison operators a lesser match when it comes
654  // to an overload resolution set with the MetaSL definitions of these operators.
655 
657  inline bool operator==( Vector_proxy_<T,DIM> rhs) const
658  {
659  return EQUAL == lexicographically_compare( *this, rhs.vec);
660  }
661 
663  inline bool operator!=( Vector_proxy_<T,DIM> rhs) const
664  {
665  return EQUAL != lexicographically_compare( *this, rhs.vec);
666  }
667 
671  inline bool operator<( Vector_proxy_<T,DIM> rhs) const
672  {
673  return lexicographically_less( *this, rhs.vec);
674  }
675 
679  inline bool operator<=( Vector_proxy_<T,DIM> rhs) const
680  {
681  return ! lexicographically_less( rhs.vec, *this);
682  }
683 
687  inline bool operator>( Vector_proxy_<T,DIM> rhs) const
688  {
689  return lexicographically_less( rhs.vec, *this);
690  }
691 
695  inline bool operator>=( Vector_proxy_<T,DIM> rhs) const
696  {
697  return ! lexicographically_less( *this, rhs.vec);
698  }
699 
700 #ifdef MI_NEURAYLIB_DEPRECATED_5_0
701 
702  inline Vector multiply( T factor) const
703  {
704  Vector<T,DIM> tmp( *this);
705  for( Size i(0u); i < DIM; ++i)
706  tmp[i] *= factor;
707  return tmp;
708  }
709 
710  inline Vector divide( T factor) const
711  {
712  Vector<T,DIM> tmp( *this);
713  if( factor != T(0))
714  for( Size i(0u); i < DIM; ++i)
715  tmp[i] /= factor;
716  return tmp;
717  }
718 
719  inline Vector add( Vector vector) const
720  {
721  Vector<T,DIM> tmp( *this);
722  for( Size i(0u); i < DIM; ++i)
723  tmp[i] += vector[i];
724  return tmp;
725  }
726 
727  inline Vector subtract( Vector vector) const
728  {
729  Vector<T,DIM> tmp( *this);
730  for( Size i(0u); i < DIM; ++i)
731  tmp[i] -= vector[i];
732  return tmp;
733  }
734 
735  inline Vector cross( Vector vector) const
736  {
737  mi_static_assert(DIM == 3);
738  return Vector<T,3>( (*this)[1] * vector[2] - (*this)[2] * vector[1],
739  (*this)[2] * vector[0] - (*this)[0] * vector[2],
740  (*this)[0] * vector[1] - (*this)[1] * vector[0]);
741  }
742 
743  inline T dot( Vector vector) const { return math::dot( *this, vector); }
744 
745  inline T norm() const { return length( *this); }
746 
747  inline T sq_norm () const { return square_length( *this); }
748 
749  inline T dist( Vector vector) const { return euclidean_distance( *this, vector); }
750 
751  inline T sq_dist( Vector vector) const { return square_euclidean_distance( *this, vector); }
752 
753  inline Vector clamp( Vector lower, Vector upper) const;
754 
755  inline Vector max MI_PREVENT_MACRO_EXPAND (Vector lower) const;
756 
757  inline Vector min MI_PREVENT_MACRO_EXPAND (Vector upper) const;
758 
759 #endif // MI_NEURAYLIB_DEPRECATED_5_0
760 };
761 
762 
763 //------ Free operators +=, -=, *=, /=, +, -, *, and / for vectors -------------
764 
766 template <typename T, Size DIM>
768  Vector<T,DIM>& lhs,
769  const Vector<T,DIM>& rhs)
770 {
771  for( Size i(0u); i < DIM; ++i)
772  lhs[i] += rhs[i];
773  return lhs;
774 }
775 
777 template <typename T, Size DIM>
779  Vector<T,DIM>& lhs,
780  const Vector<T,DIM>& rhs)
781 {
782  for( Size i(0u); i < DIM; ++i)
783  lhs[i] -= rhs[i];
784  return lhs;
785 }
786 
788 template <typename T, Size DIM>
790  Vector<T,DIM>& lhs,
791  const Vector<T,DIM>& rhs)
792 {
793  for( Size i(0u); i < DIM; ++i)
794  lhs[i] *= rhs[i];
795  return lhs;
796 }
797 
800 template <typename T, Size DIM>
802  Vector<T,DIM>& lhs,
803  const Vector<T,DIM>& rhs)
804 {
805  for( Size i(0u); i < DIM; ++i)
806  lhs[i] %= rhs[i];
807  return lhs;
808 }
809 
811 template <typename T, typename U, Size DIM>
813  Vector<T,DIM>& lhs,
814  const Vector<U,DIM>& rhs)
815 {
816  for( Size i(0u); i < DIM; ++i)
817  lhs[i] = T(lhs[i] / rhs[i]);
818  return lhs;
819 }
820 
822 template <typename T, Size DIM>
824  const Vector<T,DIM>& lhs,
825  const Vector<T,DIM>& rhs)
826 {
827  Vector<T,DIM> tmp( lhs);
828  return tmp += rhs;
829 }
830 
832 template <typename T, Size DIM>
834  const Vector<T,DIM>& lhs,
835  const Vector<T,DIM>& rhs)
836 {
837  Vector<T,DIM> tmp( lhs);
838  return tmp -= rhs;
839 }
840 
842 template <typename T, Size DIM>
844  const Vector<T,DIM>& lhs,
845  const Vector<T,DIM>& rhs)
846 {
847  Vector<T,DIM> tmp( lhs);
848  return tmp *= rhs;
849 }
850 
853 template <typename T, Size DIM>
855  const Vector<T,DIM>& lhs,
856  const Vector<T,DIM>& rhs)
857 {
858  Vector<T,DIM> tmp( lhs);
859  return tmp %= rhs;
860 }
861 
863 template <typename T, typename U, Size DIM>
865  const Vector<T,DIM>& lhs,
866  const Vector<U,DIM>& rhs)
867 {
868  Vector<T,DIM> tmp(lhs);
869  return tmp /= rhs;
870 }
871 
873 template <typename T, Size DIM>
875 {
876  Vector<T,DIM> tmp;
877  for( Size i(0u); i < DIM; ++i)
878  tmp[i] = -v[i];
879  return tmp;
880 }
881 
882 
883 //------ Free operator *=, /=, *, and / definitions for scalars ---------------
884 
887 template <typename T, typename TT, Size DIM>
889  Vector<T,DIM>& v,
890  TT s)
891 {
892  for( Size i(0u); i < DIM; ++i)
893  v[i] = T(v[i] * s);
894  return v;
895 }
896 
900 template <typename T, typename TT, Size DIM>
902  Vector<T,DIM>& v,
903  TT s)
904 {
905  for( Size i(0u); i < DIM; ++i)
906  v[i] = T(v[i] % s);
907  return v;
908 }
909 
911 template <typename T, typename TT, Size DIM>
913  Vector<T,DIM>& v,
914  TT s)
915 {
916  for( Size i(0u); i < DIM; ++i)
917  v[i] = T(v[i] / s);
918  return v;
919 }
920 
922 template <typename T, typename TT, Size DIM>
924  const Vector<T,DIM>& v,
925  TT s)
926 {
927  Vector<T,DIM> tmp( v);
928  return tmp *= s;
929 }
930 
932 template <typename T, typename TT, Size DIM>
934  TT s,
935  const Vector<T,DIM>& v)
936 {
937  Vector<T,DIM> tmp(v);
938  return tmp *= s;
939 }
940 
944 template <typename T, typename TT, Size DIM>
946  const Vector<T,DIM>& v,
947  TT s)
948 {
949  Vector<T,DIM> tmp(v);
950  return tmp %= s;
951 }
952 
954 template <typename T, typename TT, Size DIM>
956  const Vector<T,DIM>& v,
957  TT s)
958 {
959  Vector<T,DIM> tmp( v);
960  return tmp /= s;
961 }
962 
963 
964 //------ Free operator ++, -- for vectors -------------------------------------
965 
967 template <typename T, Size DIM>
969 {
971  return vec;
972 }
973 
975 template <typename T, Size DIM>
977 {
979  return vec;
980 }
981 
982 
983 //------ Free operators !, &&, ||, ^ for bool vectors and bool scalars ---------
984 
986 template <Size DIM>
988  const Vector<bool,DIM>& lhs,
989  const Vector<bool,DIM>& rhs)
990 {
991  Vector<bool,DIM> result;
992  general::transform( lhs, rhs, result, functor::Operator_and_and());
993  return result;
994 }
995 
997 template <Size DIM>
999  bool lhs,
1000  const Vector<bool,DIM>& rhs)
1001 {
1002  Vector<bool,DIM> result;
1004  return result;
1005 }
1006 
1008 template <Size DIM>
1010  const Vector<bool,DIM>& lhs,
1011  bool rhs)
1012 {
1013  Vector<bool,DIM> result;
1015  return result;
1016 }
1017 
1019 template <Size DIM>
1021  const Vector<bool,DIM>& lhs,
1022  const Vector<bool,DIM>& rhs)
1023 {
1024  Vector<bool,DIM> result;
1025  general::transform(lhs, rhs, result, functor::Operator_or_or());
1026  return result;
1027 }
1028 
1030 template <Size DIM>
1032  bool lhs,
1033  const Vector<bool,DIM>& rhs)
1034 {
1035  Vector<bool,DIM> result;
1037  return result;
1038 }
1039 
1041 template <Size DIM>
1043  const Vector<bool,DIM>& lhs,
1044  bool rhs)
1045 {
1046  Vector<bool,DIM> result;
1048  return result;
1049 }
1050 
1052 template <Size DIM>
1054  const Vector<bool,DIM>& lhs,
1055  const Vector<bool,DIM>& rhs)
1056 {
1057  Vector<bool,DIM> result;
1058  general::transform( lhs, rhs, result, functor::Operator_xor());
1059  return result;
1060 }
1061 
1063 template <Size DIM>
1065  bool lhs,
1066  const Vector<bool,DIM>& rhs)
1067 {
1068  Vector<bool,DIM> result;
1070  return result;
1071 }
1072 
1074 template <Size DIM>
1076  const Vector<bool,DIM>& lhs,
1077  bool rhs)
1078 {
1079  Vector<bool,DIM> result;
1081  return result;
1082 }
1083 
1085 template <Size DIM>
1087  const Vector<bool,DIM>& vec)
1088 {
1089  Vector<bool,DIM> result;
1090  general::transform( vec, result, functor::Operator_not());
1091  return result;
1092 }
1093 
1094 
1095 //------ Elementwise comparison operators returning a bool vector. ------------
1096 
1098 template <typename T, Size DIM>
1100  const Vector<T,DIM>& lhs,
1101  const Vector<T,DIM>& rhs)
1102 {
1103  Vector<bool,DIM> result;
1105  return result;
1106 }
1107 
1109 template <typename T, Size DIM>
1111  const Vector<T,DIM>& lhs,
1112  const Vector<T,DIM>& rhs)
1113 {
1114  Vector<bool,DIM> result;
1115  general::transform( lhs, rhs, result,functor::Operator_not_equal());
1116  return result;
1117 }
1118 
1120 template <typename T, Size DIM>
1122  const Vector<T,DIM>& lhs,
1123  const Vector<T,DIM>& rhs)
1124 {
1125  Vector<bool,DIM> result;
1126  general::transform( lhs, rhs, result,functor::Operator_less());
1127  return result;
1128 }
1129 
1131 template <typename T, Size DIM>
1133  const Vector<T,DIM>& lhs,
1134  const Vector<T,DIM>& rhs)
1135 {
1136  Vector<bool,DIM> result;
1137  general::transform( lhs, rhs, result,functor::Operator_less_equal());
1138  return result;
1139 }
1140 
1142 template <typename T, Size DIM>
1144  const Vector<T,DIM>& lhs,
1145  const Vector<T,DIM>& rhs)
1146 {
1147  Vector<bool,DIM> result;
1148  general::transform( lhs, rhs, result,functor::Operator_greater());
1149  return result;
1150 }
1151 
1153 template <typename T, Size DIM>
1155  const Vector<T,DIM>& lhs,
1156  const Vector<T,DIM>& rhs)
1157 {
1158  Vector<bool,DIM> result;
1160  return result;
1161 }
1162 
1163 
1164 //------ Function Overloads for Vector Algorithms -----------------------------
1165 
1167 template <typename T, Size DIM>
1169 {
1170  Vector<T,DIM> result;
1171  for( Size i = 0; i != DIM; ++i)
1172  result[i] = abs( v[i]);
1173  return result;
1174 }
1175 
1177 template <typename T, Size DIM>
1179 {
1180  Vector<T,DIM> result;
1181  for( Size i = 0; i != DIM; ++i)
1182  result[i] = acos( v[i]);
1183  return result;
1184 }
1185 
1187 template <typename T, Size DIM>
1188 inline bool all( const Vector<T,DIM>& v)
1189 {
1190  for( Size i = 0; i != DIM; ++i)
1191  if( !all(v[i]))
1192  return false;
1193  return true;
1194 }
1195 
1197 template <typename T, Size DIM>
1198 inline bool any( const Vector<T,DIM>& v)
1199 {
1200  for( Size i = 0; i != DIM; ++i)
1201  if( any(v[i]))
1202  return true;
1203  return false;
1204 }
1205 
1207 template <typename T, Size DIM>
1209 {
1210  Vector<T,DIM> result;
1211  for( Size i = 0; i != DIM; ++i)
1212  result[i] = asin( v[i]);
1213  return result;
1214 }
1215 
1217 template <typename T, Size DIM>
1219 {
1220  Vector<T,DIM> result;
1221  for( Size i = 0; i != DIM; ++i)
1222  result[i] = atan( v[i]);
1223  return result;
1224 }
1225 
1229 template <typename T, Size DIM>
1230 inline Vector<T,DIM> atan2( const Vector<T,DIM>& v, const Vector<T,DIM>& w)
1231 {
1232  Vector<T,DIM> result;
1233  for( Size i = 0; i != DIM; ++i)
1234  result[i] = atan2( v[i], w[i]);
1235  return result;
1236 }
1237 
1240 template <typename T, Size DIM>
1242 {
1243  Vector<T,DIM> result;
1244  for( Size i = 0; i != DIM; ++i)
1245  result[i] = ceil( v[i]);
1246  return result;
1247 }
1248 
1250 template <typename T, Size DIM>
1252  const Vector<T,DIM>& v,
1253  const Vector<T,DIM>& low,
1254  const Vector<T,DIM>& high)
1255 {
1256  Vector<T,DIM> result;
1257  for( Size i = 0u; i < DIM; ++i)
1258  result[i] = clamp( v[i], low[i], high[i]);
1259  return result;
1260 }
1261 
1263 template <typename T, Size DIM>
1265  const Vector<T,DIM>& v,
1266  const Vector<T,DIM>& low,
1267  T high)
1268 {
1269  Vector<T,DIM> result;
1270  for( Size i = 0u; i < DIM; ++i)
1271  result[i] = clamp( v[i], low[i], high);
1272  return result;
1273 }
1274 
1276 template <typename T, Size DIM>
1278  const Vector<T,DIM>& v,
1279  T low,
1280  const Vector<T,DIM>& high)
1281 {
1282  Vector<T,DIM> result;
1283  for( Size i = 0u; i < DIM; ++i)
1284  result[i] = clamp( v[i], low, high[i]);
1285  return result;
1286 }
1287 
1289 template <typename T, Size DIM>
1291  const Vector<T,DIM>& v,
1292  T low,
1293  T high)
1294 {
1295  Vector<T,DIM> result;
1296  for( Size i = 0u; i < DIM; ++i)
1297  result[i] = clamp( v[i], low, high);
1298  return result;
1299 }
1300 
1302 template <typename T, Size DIM>
1304 {
1305  Vector<T,DIM> result;
1306  for( Size i = 0; i != DIM; ++i)
1307  result[i] = cos( v[i]);
1308  return result;
1309 }
1310 
1312 template <typename T, Size DIM>
1314 {
1315  Vector<T,DIM> result;
1316  for( Size i = 0; i != DIM; ++i)
1317  result[i] = degrees( v[i]);
1318  return result;
1319 }
1320 
1322 template <typename T, Size DIM>
1324  const Vector<T,DIM>& lhs,
1325  const Vector<T,DIM>& rhs)
1326 {
1327  Vector<T,DIM> r;
1328  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1329  r[i] = base::max MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1330  return r;
1331 }
1332 
1334 template <typename T, Size DIM>
1336  const Vector<T,DIM>& lhs,
1337  const Vector<T,DIM>& rhs)
1338 {
1339  Vector<T,DIM> r;
1340  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1341  r[i] = base::min MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1342  return r;
1343 }
1344 
1346 template <typename T, Size DIM>
1348 {
1349  Vector<T,DIM> result;
1350  for( Size i = 0; i != DIM; ++i)
1351  result[i] = exp( v[i]);
1352  return result;
1353 }
1354 
1356 template <typename T, Size DIM>
1358 {
1359  Vector<T,DIM> result;
1360  for( Size i = 0; i != DIM; ++i)
1361  result[i] = exp2( v[i]);
1362  return result;
1363 }
1364 
1367 template <typename T, Size DIM>
1369 {
1370  Vector<T,DIM> result;
1371  for( Size i = 0; i != DIM; ++i)
1372  result[i] = floor( v[i]);
1373  return result;
1374 }
1375 
1379 template <typename T, Size DIM>
1380 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1381 {
1382  Vector<T,DIM> result;
1383  for( Size i = 0; i != DIM; ++i)
1384  result[i] = fmod( a[i], b[i]);
1385  return result;
1386 }
1387 
1391 template <typename T, Size DIM>
1392 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, T b)
1393 {
1394  Vector<T,DIM> result;
1395  for( Size i = 0; i != DIM; ++i)
1396  result[i] = fmod( a[i], b);
1397  return result;
1398 }
1399 
1401 template <typename T, Size DIM>
1403 {
1404  Vector<T,DIM> result;
1405  for( Size i = 0; i != DIM; ++i)
1406  result[i] = frac( v[i]);
1407  return result;
1408 }
1409 
1411 template <typename T, Size DIM>
1412 inline bool is_approx_equal(
1413  const Vector<T,DIM>& left,
1414  const Vector<T,DIM>& right,
1415  T e)
1416 {
1417  for( Size i = 0u; i < DIM; ++i)
1418  if( !is_approx_equal( left[i], right[i], e))
1419  return false;
1420  return true;
1421 }
1422 
1425 template <typename T, Size DIM>
1427  const Vector<T,DIM>& v1,
1428  const Vector<T,DIM>& v2,
1429  const Vector<T,DIM>& t)
1430 {
1431  Vector<T,DIM> result;
1432  for( Size i = 0; i != DIM; ++i)
1433  result[i] = v1[i] * (T(1)-t[i]) + v2[i] * t[i];
1434  return result;
1435 }
1436 
1439 template <typename T, Size DIM>
1441  const Vector<T,DIM>& v1,
1442  const Vector<T,DIM>& v2,
1443  T t)
1444 {
1445  // equivalent to: return v1 * (T(1)-t) + v2 * t;
1446  Vector<T,DIM> result;
1447  T t2 = T(1) - t;
1448  for( Size i = 0; i != DIM; ++i)
1449  result[i] = v1[i] * t2 + v2[i] * t;
1450  return result;
1451 }
1452 
1454 template <typename T, Size DIM>
1456 {
1457  Vector<T,DIM> result;
1458  for( Size i = 0; i != DIM; ++i)
1459  result[i] = log( v[i]);
1460  return result;
1461 }
1462 
1464 template <typename T, Size DIM>
1466 {
1467  Vector<T,DIM> result;
1468  for( Size i = 0; i != DIM; ++i)
1469  result[i] = log2 MI_PREVENT_MACRO_EXPAND ( v[i]);
1470  return result;
1471 }
1472 
1474 template <typename T, Size DIM>
1476 {
1477  Vector<T,DIM> result;
1478  for( Size i = 0; i != DIM; ++i)
1479  result[i] = log10( v[i]);
1480  return result;
1481 }
1482 
1487 template <typename T, Size DIM>
1489 {
1490  Vector<T,DIM> result;
1491  for( Size j = 0; j != DIM; ++j)
1492  result[j] = modf( v[j], i[j]);
1493  return result;
1494 }
1495 
1497 template <typename T, Size DIM>
1498 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1499 {
1500  Vector<T,DIM> result;
1501  for( Size i = 0; i != DIM; ++i)
1502  result[i] = pow( a[i], b[i]);
1503  return result;
1504 }
1505 
1507 template <typename T, Size DIM>
1508 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, T b)
1509 {
1510  Vector<T,DIM> result;
1511  for( Size i = 0; i != DIM; ++i)
1512  result[i] = pow( a[i], b);
1513  return result;
1514 }
1515 
1517 template <typename T, Size DIM>
1519 {
1520  Vector<T,DIM> result;
1521  for( Size i = 0; i != DIM; ++i)
1522  result[i] = radians( v[i]);
1523  return result;
1524 }
1525 
1527 template <typename T, Size DIM>
1529 {
1530  Vector<T,DIM> result;
1531  for( Size i = 0; i != DIM; ++i)
1532  result[i] = round( v[i]);
1533  return result;
1534 }
1535 
1537 template <typename T, Size DIM>
1539 {
1540  Vector<T,DIM> result;
1541  for( Size i = 0; i != DIM; ++i)
1542  result[i] = rsqrt( v[i]);
1543  return result;
1544 }
1545 
1547 template <typename T, Size DIM>
1549 {
1550  Vector<T,DIM> result;
1551  for( Size i = 0; i != DIM; ++i)
1552  result[i] = saturate( v[i]);
1553  return result;
1554 }
1555 
1557 template <typename T, Size DIM>
1559 {
1560  Vector<T,DIM> result;
1561  for( Size i = 0; i != DIM; ++i)
1562  result[i] = sign( v[i]);
1563  return result;
1564 }
1565 
1567 template <typename T, Size DIM>
1569 {
1570  Vector<T,DIM> result;
1571  for( Size i = 0; i != DIM; ++i)
1572  result[i] = sin( v[i]);
1573  return result;
1574 }
1575 
1579 template <typename T, Size DIM>
1580 inline void sincos( const Vector<T,DIM>& a, Vector<T,DIM>& s, Vector<T,DIM>& c)
1581 {
1582  for( Size i = 0; i != DIM; ++i)
1583  sincos( a[i], s[i], c[i]);
1584 }
1585 
1591 template <typename T, Size DIM>
1593  const Vector<T,DIM>& a,
1594  const Vector<T,DIM>& b,
1595  const Vector<T,DIM>& v)
1596 {
1597  Vector<T,DIM> result;
1598  for( Size i = 0; i != DIM; ++i)
1599  result[i] = smoothstep( a[i], b[i], v[i]);
1600  return result;
1601 }
1602 
1608 template <typename T, Size DIM>
1610  const Vector<T,DIM>& a,
1611  const Vector<T,DIM>& b,
1612  T x)
1613 {
1614  Vector<T,DIM> result;
1615  for( Size i = 0; i != DIM; ++i)
1616  result[i] = smoothstep( a[i], b[i], x);
1617  return result;
1618 }
1619 
1621 template <typename T, Size DIM>
1623 {
1624  Vector<T,DIM> result;
1625  for( Size i = 0; i != DIM; ++i)
1626  result[i] = sqrt( v[i]);
1627  return result;
1628 }
1629 
1631 template <typename T, Size DIM>
1632 inline Vector<T,DIM> step( const Vector<T,DIM>& a, const Vector<T,DIM>& v)
1633 {
1634  Vector<T,DIM> result;
1635  for( Size i = 0; i != DIM; ++i)
1636  result[i] = step( a[i], v[i]);
1637  return result;
1638 }
1639 
1641 template <typename T, Size DIM>
1643 {
1644  Vector<T,DIM> result;
1645  for( Size i = 0; i != DIM; ++i)
1646  result[i] = tan( v[i]);
1647  return result;
1648 }
1649 
1650 
1651 //------ Geometric Vector Algorithms ------------------------------------------
1652 
1654 template <typename T>
1655 inline T cross(
1656  const Vector<T,2>& lhs,
1657  const Vector<T,2>& rhs)
1658 {
1659  return lhs.x * rhs.y - lhs.y * rhs.x;
1660 }
1661 
1663 template <typename T>
1665  const Vector<T,3>& lhs,
1666  const Vector<T,3>& rhs)
1667 {
1668  return Vector<T,3>( lhs.y * rhs.z - lhs.z * rhs.y,
1669  lhs.z * rhs.x - lhs.x * rhs.z,
1670  lhs.x * rhs.y - lhs.y * rhs.x);
1671 }
1672 
1678 template <typename T>
1679 inline void make_basis(
1680  const Vector<T,3>& n,
1681  Vector<T,3>* u,
1682  Vector<T,3>* v)
1683 {
1684 #ifdef mi_base_assert_enabled
1685  const T eps = 1e-6f; // smallest resolvable factor
1686 #endif
1687 
1688  mi_math_assert_msg( u != 0, "precondition");
1689  mi_math_assert_msg( v != 0, "precondition");
1690  // Sanity check: the normal vector must be unit length.
1691  mi_math_assert_msg( abs( length(n) - 1.0f) < eps, "precondition");
1692 
1693  // Compute u.
1694  if( abs(n.x) < abs(n.y)) {
1695  // u = cross(x, n), x = (1, 0, 0)
1696  u->x = T(0);
1697  u->y = -n.z;
1698  u->z = n.y;
1699  } else {
1700  // u = cross(y, n), y = (0, 1, 0)
1701  u->x = n.z;
1702  u->y = T(0);
1703  u->z = -n.x;
1704  }
1705  u->normalize();
1706 
1707  // Compute v. Since *u and n are orthogonal and unit-length,
1708  // there is no need to normalize *v.
1709  *v = cross( *u, n);
1710 
1711  // Sanity check: make sure (u, n, v) is an orthogonal basis.
1712  mi_math_assert_msg( abs( dot( *u, n)) < eps, "postcondition");
1713  mi_math_assert_msg( abs( dot( *u, *v)) < eps, "postcondition");
1714  mi_math_assert_msg( abs( dot( n, *v)) < eps, "postcondition");
1715  // Sanity check: make sure u and v are unit length.
1716  mi_math_assert_msg( abs( length( *u) - T(1)) < eps, "postcondition");
1717  mi_math_assert_msg( abs( length( *v) - T(1)) < eps, "postcondition");
1718 }
1719 
1726 template <typename T>
1727 inline void make_basis(
1728  const Vector<T,3>& n,
1729  const Vector<T,3>& u,
1730  const Vector<T,3>& v,
1731  Vector<T,3>* t,
1732  Vector<T,3>* b)
1733 {
1734  const T eps = 1e-6f; // smallest resolvable factor
1735  (void)eps;
1736 
1737  mi_math_assert_msg( t != 0, "precondition");
1738  mi_math_assert_msg( b != 0, "precondition");
1739  // Sanity check: the normal vector must be unit length.
1740  mi_math_assert_msg( abs( length( n) - 1.0f) < eps, "precondition");
1741  // Sanity check: the other vector lengths should be finite and non-zero
1742  mi_math_assert_msg( length( u) > 0., "precondition");
1743  mi_math_assert_msg( length( v) > 0., "precondition");
1744  mi_math_assert_msg( isfinite( length( u)), "precondition");
1745  mi_math_assert_msg( isfinite( length( v)), "precondition");
1746 
1747  // Compute b
1748  *b = cross(u,n);
1749  b->normalize();
1750 
1751  // Compute t. Since *b and n are orthogonal and unit-length,
1752  // there is no need to normalize *t.
1753  *t = cross(n,*b);
1754 
1755  // Check that b has the same orientation of v
1756  if( dot( *b,v) < T(0))
1757  *b = -*b;
1758 
1759  // Sanity check: make sure *u and t have the same orientation.
1760  mi_math_assert_msg( dot( u, *t) > T(0), "postcondition");
1761  // Sanity check: make sure (t, n, b) is an orthogonal basis.
1762  // We use a scaled epsilon in order to avoid false positives.
1763  mi_math_assert_msg( abs( dot( *t, n)) < 20*eps, "postcondition");
1764  mi_math_assert_msg( abs( dot( *t, *b)) < 20*eps, "postcondition");
1765  mi_math_assert_msg( abs( dot( n, *b)) < 20*eps, "postcondition");
1766  // Sanity check: make sure t and b are unit length.
1767  mi_math_assert_msg( abs( length( *t) - T(1)) < eps, "postcondition");
1768  mi_math_assert_msg( abs( length( *b) - T(1)) < eps, "postcondition");
1769 }
1770 
1776 template <typename T2, Size DIM2, typename T1, Size DIM1>
1778  const Vector<T1, DIM1>& v,
1779  const T2& fill = T2(0))
1780 {
1781  const Size dim_min = base::min MI_PREVENT_MACRO_EXPAND ( DIM1, DIM2 );
1782  Vector<T2, DIM2> result;
1783  for( Size i = 0; i < dim_min; ++i)
1784  result[i] = T2(v[i]);
1785  for( Size i = dim_min; i < DIM2; ++i)
1786  result[i] = fill;
1787  return result;
1788 }
1789 
1790 #ifdef MI_NEURAYLIB_DEPRECATED_5_0
1791 
1792 template <typename T, Size DIM>
1793 inline Vector<T,DIM> Vector<T,DIM>::clamp (Vector<T,DIM> lower, Vector<T,DIM> upper) const
1794 {
1795  return math::clamp( *this, lower, upper);
1796 }
1797 
1798 template <typename T, Size DIM>
1799 inline Vector<T,DIM> Vector<T,DIM>::max MI_PREVENT_MACRO_EXPAND (Vector<T,DIM> lower) const
1800 {
1801  return math::elementwise_max( *this, lower);
1802 }
1803 
1804 template <typename T, Size DIM>
1805 inline Vector<T,DIM> Vector<T,DIM>::min MI_PREVENT_MACRO_EXPAND (Vector<T,DIM> upper) const
1806 {
1807  return math::elementwise_min( *this, upper);
1808 }
1809 
1810 #endif // MI_NEURAYLIB_DEPRECATED_5_0
1811  // end group mi_math_vector
1813 
1814 } // namespace math
1815 
1816 } // namespace mi
1817 
1818 #endif // MI_MATH_VECTOR_H