MDL SDK API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vector.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  * Copyright 2022 NVIDIA Corporation. All rights reserved.
3  **************************************************************************************************/
9 
10 #ifndef MI_MATH_VECTOR_H
11 #define MI_MATH_VECTOR_H
12 
13 #include <mi/base/types.h>
14 #include <mi/math/assert.h>
15 #include <mi/math/function.h>
16 
17 namespace mi {
18 
19 namespace math {
20 
38 };
39 
40 
41 // Color and Vector can be converted into each other. To avoid cyclic dependencies among the
42 // headers, the Color_struct class is already defined here.
43 
44 //------- POD struct that provides storage for color elements --------
45 
67 {
76 };
77 
78 
105 //------- POD struct that provides storage for vector elements --------
106 
133 template <typename T, Size DIM>
135 {
136  T elements[DIM];
137 };
138 
140 template <typename T> struct Vector_struct<T, 1>
141 {
142  T x;
143 };
144 
146 template <typename T> struct Vector_struct<T, 2>
147 {
148  T x;
149  T y;
150 };
151 
153 template <typename T> struct Vector_struct<T, 3>
154 {
155  T x;
156  T y;
157  T z;
158 };
159 
161 template <typename T> struct Vector_struct<T, 4>
162 {
163  T x;
164  T y;
165  T z;
166  T w;
167 };
168 
169 
170 //------ Indirect access to vector storage base ptr to keep Vector_struct a POD --
171 
173 template <typename T, Size DIM>
175 {
176  return vec.elements;
177 }
178 
180 template <typename T, Size DIM>
181 inline const T* vector_base_ptr( const Vector_struct<T,DIM>& vec)
182 {
183  return vec.elements;
184 }
185 
187 template <typename T>
189 {
190  return &vec.x;
191 }
192 
194 template <typename T>
195 inline const T* vector_base_ptr( const Vector_struct<T,1>& vec)
196 {
197  return &vec.x;
198 }
199 
201 template <typename T>
203 {
204  return &vec.x;
205 }
206 
208 template <typename T>
209 inline const T* vector_base_ptr( const Vector_struct<T,2>& vec)
210 {
211  return &vec.x;
212 }
213 
215 template <typename T>
217 {
218  return &vec.x;
219 }
220 
222 template <typename T>
223 inline const T* vector_base_ptr( const Vector_struct<T,3>& vec)
224 {
225  return &vec.x;
226 }
227 
229 template <typename T>
231 {
232  return &vec.x;
233 }
234 
236 template <typename T>
237 inline const T* vector_base_ptr( const Vector_struct<T,4>& vec)
238 {
239  return &vec.x;
240 }
241 
242  // end group mi_math_vector_struct
244 
245 
246 //------ Generic Vector Class -------------------------------------------------
247 
284 template < class T, Size DIM>
285 class Vector : public Vector_struct<T, DIM> //-V690 PVS
286 {
287 public:
290 
291  typedef T value_type;
292  typedef Size size_type;
294  typedef T * pointer;
295  typedef const T * const_pointer;
296  typedef T & reference;
297  typedef const T & const_reference;
298 
299  static const Size DIMENSION = DIM;
300  static const Size SIZE = DIM;
301 
303  static inline Size size() { return SIZE; }
304 
306  static inline Size max_size() { return SIZE; }
307 
309  inline T* begin() { return mi::math::vector_base_ptr( *this); }
310 
312  inline const T* begin() const { return mi::math::vector_base_ptr( *this); }
313 
317  inline T* end() { return begin() + DIM; }
318 
322  inline const T* end() const { return begin() + DIM; }
323 
325  inline Vector()
326  {
327 #if defined(DEBUG) || (defined(_MSC_VER) && _MSC_VER <= 1310)
328  // In debug mode, default-constructed vectors are initialized with signaling NaNs or, if not
329  // applicable, with a maximum value to increase the chances of diagnosing incorrect use of
330  // an uninitialized vector.
331  //
332  // When compiling with Visual C++ 7.1 or earlier, this code is enabled in all variants to
333  // work around a very obscure compiler bug that causes the compiler to crash.
334  typedef mi::base::numeric_traits<T> Traits;
335  T v = (Traits::has_signaling_NaN) ? Traits::signaling_NaN()
336  : Traits::max MI_PREVENT_MACRO_EXPAND ();
337  for( Size i(0u); i < DIM; ++i)
338  (*this)[i] = v;
339 #endif
340  }
341 
342 #if (__cplusplus >= 201103L)
343  Vector( const Vector<T,DIM>& vec ) = default;
345 #endif
346 
348  inline Vector( const Vector_struct<T,DIM>& vec )
349  {
350  for( Size i(0u); i < DIM; ++i)
351  (*this)[i] = mi::math::vector_base_ptr(vec)[i];
352  }
353 
355  inline explicit Vector(T v)
356  {
357  for( Size i(0u); i < DIM; ++i)
358  (*this)[i] = v;
359  }
360 
374  template <typename Iterator>
375  inline Vector(From_iterator_tag, Iterator p)
376  {
377  for( Size i(0u); i < DIM; ++i, ++p)
378  (*this)[i] = *p;
379  }
380 
392  template <typename T2>
393  inline explicit Vector( T2 const (& array)[DIM])
394  {
395  for( Size i(0u); i < DIM; ++i)
396  (*this)[i] = array[i];
397  }
398 
401  template <typename T2>
402  inline explicit Vector( const Vector<T2,DIM>& other)
403  {
404  for( Size i(0u); i < DIM; ++i)
405  (*this)[i] = T(other[i]);
406  }
407 
410  template <typename T2>
411  inline explicit Vector( const Vector_struct<T2,DIM>& other)
412  {
413  for( Size i(0u); i < DIM; ++i)
414  (*this)[i] = T(mi::math::vector_base_ptr(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); //-V601 PVS
646  if( result)
647  (*this) *= rec_length;
648  return result;
649  }
650 
651 
652  //------ Free comparison operators ==, !=, <, <=, >, >= for vectors --------
653 
655  inline bool operator==( Vector<T,DIM> rhs) const
656  {
657  return is_equal( *this, rhs);
658  }
659 
661  inline bool operator!=( Vector<T,DIM> rhs) const
662  {
663  return is_not_equal( *this, rhs);
664  }
665 
669  inline bool operator<( Vector<T,DIM> rhs) const
670  {
671  return lexicographically_less( *this, rhs);
672  }
673 
677  inline bool operator<=( Vector<T,DIM> rhs) const
678  {
679  return lexicographically_less_or_equal( *this, rhs);
680  }
681 
685  inline bool operator>( Vector<T,DIM> rhs) const
686  {
687  return lexicographically_greater( *this, rhs);
688  }
689 
693  inline bool operator>=( Vector<T,DIM> rhs) const
694  {
695  return lexicographically_greater_or_equal( *this, rhs);
696  }
697 };
698 
699 
700 //------ Free operators +=, -=, *=, /=, +, -, *, and / for vectors -------------
701 
703 template <typename T, Size DIM>
705  Vector<T,DIM>& lhs,
706  const Vector<T,DIM>& rhs)
707 {
708  for( Size i(0u); i < DIM; ++i)
709  lhs[i] += rhs[i];
710  return lhs;
711 }
712 
714 template <typename T, Size DIM>
716  Vector<T,DIM>& lhs,
717  const Vector<T,DIM>& rhs)
718 {
719  for( Size i(0u); i < DIM; ++i)
720  lhs[i] -= rhs[i];
721  return lhs;
722 }
723 
725 template <typename T, Size DIM>
727  Vector<T,DIM>& lhs,
728  const Vector<T,DIM>& rhs)
729 {
730  for( Size i(0u); i < DIM; ++i)
731  lhs[i] *= rhs[i];
732  return lhs;
733 }
734 
737 template <typename T, Size DIM>
739  Vector<T,DIM>& lhs,
740  const Vector<T,DIM>& rhs)
741 {
742  for( Size i(0u); i < DIM; ++i)
743  lhs[i] %= rhs[i];
744  return lhs;
745 }
746 
748 template <typename T, typename U, Size DIM>
750  Vector<T,DIM>& lhs,
751  const Vector<U,DIM>& rhs)
752 {
753  for( Size i(0u); i < DIM; ++i)
754  lhs[i] = T(lhs[i] / rhs[i]);
755  return lhs;
756 }
757 
759 template <typename T, Size DIM>
761  const Vector<T,DIM>& lhs,
762  const Vector<T,DIM>& rhs)
763 {
764  Vector<T,DIM> tmp( lhs);
765  return tmp += rhs;
766 }
767 
769 template <typename T, Size DIM>
771  const Vector<T,DIM>& lhs,
772  const Vector<T,DIM>& rhs)
773 {
774  Vector<T,DIM> tmp( lhs);
775  return tmp -= rhs;
776 }
777 
779 template <typename T, Size DIM>
781  const Vector<T,DIM>& lhs,
782  const Vector<T,DIM>& rhs)
783 {
784  Vector<T,DIM> tmp( lhs);
785  return tmp *= rhs;
786 }
787 
790 template <typename T, Size DIM>
792  const Vector<T,DIM>& lhs,
793  const Vector<T,DIM>& rhs)
794 {
795  Vector<T,DIM> tmp( lhs);
796  return tmp %= rhs;
797 }
798 
800 template <typename T, typename U, Size DIM>
802  const Vector<T,DIM>& lhs,
803  const Vector<U,DIM>& rhs)
804 {
805  Vector<T,DIM> tmp(lhs);
806  return tmp /= rhs;
807 }
808 
810 template <typename T, Size DIM>
812 {
813  Vector<T,DIM> tmp;
814  for( Size i(0u); i < DIM; ++i)
815  tmp[i] = -v[i];
816  return tmp;
817 }
818 
819 
820 //------ Free operator *=, /=, *, and / definitions for scalars ---------------
821 
824 template <typename T, typename TT, Size DIM>
826  Vector<T,DIM>& v,
827  TT s)
828 {
829  for( Size i(0u); i < DIM; ++i)
830  v[i] = T(v[i] * s);
831  return v;
832 }
833 
837 template <typename T, typename TT, Size DIM>
839  Vector<T,DIM>& v,
840  TT s)
841 {
842  for( Size i(0u); i < DIM; ++i)
843  v[i] = T(v[i] % s);
844  return v;
845 }
846 
848 template <typename T, typename TT, Size DIM>
850  Vector<T,DIM>& v,
851  TT s)
852 {
853  for( Size i(0u); i < DIM; ++i)
854  v[i] = T(v[i] / s);
855  return v;
856 }
857 
859 template <typename T, typename TT, Size DIM>
861  const Vector<T,DIM>& v,
862  TT s)
863 {
864  Vector<T,DIM> tmp( v);
865  return tmp *= s;
866 }
867 
869 template <typename T, typename TT, Size DIM>
871  TT s,
872  const Vector<T,DIM>& v)
873 {
874  Vector<T,DIM> tmp(v);
875  return tmp *= s;
876 }
877 
881 template <typename T, typename TT, Size DIM>
883  const Vector<T,DIM>& v,
884  TT s)
885 {
886  Vector<T,DIM> tmp(v);
887  return tmp %= s;
888 }
889 
891 template <typename T, typename TT, Size DIM>
893  const Vector<T,DIM>& v,
894  TT s)
895 {
896  Vector<T,DIM> tmp( v);
897  return tmp /= s;
898 }
899 
900 
901 //------ Free operator ++, -- for vectors -------------------------------------
902 
904 template <typename T, Size DIM>
906 {
908  return vec;
909 }
910 
912 template <typename T, Size DIM>
914 {
916  return vec;
917 }
918 
919 
920 //------ Free operators !, &&, ||, ^ for bool vectors and bool scalars ---------
921 
923 template <Size DIM>
925  const Vector<bool,DIM>& lhs,
926  const Vector<bool,DIM>& rhs)
927 {
928  Vector<bool,DIM> result;
929  general::transform( lhs, rhs, result, functor::Operator_and_and());
930  return result;
931 }
932 
934 template <Size DIM>
936  bool lhs,
937  const Vector<bool,DIM>& rhs)
938 {
939  Vector<bool,DIM> result;
941  return result;
942 }
943 
945 template <Size DIM>
947  const Vector<bool,DIM>& lhs,
948  bool rhs)
949 {
950  Vector<bool,DIM> result;
952  return result;
953 }
954 
956 template <Size DIM>
958  const Vector<bool,DIM>& lhs,
959  const Vector<bool,DIM>& rhs)
960 {
961  Vector<bool,DIM> result;
962  general::transform(lhs, rhs, result, functor::Operator_or_or());
963  return result;
964 }
965 
967 template <Size DIM>
969  bool lhs,
970  const Vector<bool,DIM>& rhs)
971 {
972  Vector<bool,DIM> result;
974  return result;
975 }
976 
978 template <Size DIM>
980  const Vector<bool,DIM>& lhs,
981  bool rhs)
982 {
983  Vector<bool,DIM> result;
985  return result;
986 }
987 
989 template <Size DIM>
991  const Vector<bool,DIM>& lhs,
992  const Vector<bool,DIM>& rhs)
993 {
994  Vector<bool,DIM> result;
995  general::transform( lhs, rhs, result, functor::Operator_xor());
996  return result;
997 }
998 
1000 template <Size DIM>
1002  bool lhs,
1003  const Vector<bool,DIM>& rhs)
1004 {
1005  Vector<bool,DIM> result;
1007  return result;
1008 }
1009 
1011 template <Size DIM>
1013  const Vector<bool,DIM>& lhs,
1014  bool rhs)
1015 {
1016  Vector<bool,DIM> result;
1018  return result;
1019 }
1020 
1022 template <Size DIM>
1024  const Vector<bool,DIM>& vec)
1025 {
1026  Vector<bool,DIM> result;
1027  general::transform( vec, result, functor::Operator_not());
1028  return result;
1029 }
1030 
1031 
1032 //------ Elementwise comparison operators returning a bool vector. ------------
1033 
1035 template <typename T, Size DIM>
1037  const Vector<T,DIM>& lhs,
1038  const Vector<T,DIM>& rhs)
1039 {
1040  Vector<bool,DIM> result;
1042  return result;
1043 }
1044 
1046 template <typename T, Size DIM>
1048  const Vector<T,DIM>& lhs,
1049  const Vector<T,DIM>& rhs)
1050 {
1051  Vector<bool,DIM> result;
1052  general::transform( lhs, rhs, result,functor::Operator_not_equal());
1053  return result;
1054 }
1055 
1057 template <typename T, Size DIM>
1059  const Vector<T,DIM>& lhs,
1060  const Vector<T,DIM>& rhs)
1061 {
1062  Vector<bool,DIM> result;
1063  general::transform( lhs, rhs, result,functor::Operator_less());
1064  return result;
1065 }
1066 
1068 template <typename T, Size DIM>
1070  const Vector<T,DIM>& lhs,
1071  const Vector<T,DIM>& rhs)
1072 {
1073  Vector<bool,DIM> result;
1074  general::transform( lhs, rhs, result,functor::Operator_less_equal());
1075  return result;
1076 }
1077 
1079 template <typename T, Size DIM>
1081  const Vector<T,DIM>& lhs,
1082  const Vector<T,DIM>& rhs)
1083 {
1084  Vector<bool,DIM> result;
1085  general::transform( lhs, rhs, result,functor::Operator_greater());
1086  return result;
1087 }
1088 
1090 template <typename T, Size DIM>
1092  const Vector<T,DIM>& lhs,
1093  const Vector<T,DIM>& rhs)
1094 {
1095  Vector<bool,DIM> result;
1097  return result;
1098 }
1099 
1100 
1101 //------ Function Overloads for Vector Algorithms -----------------------------
1102 
1104 template <typename T, Size DIM>
1106 {
1107  Vector<T,DIM> result;
1108  for( Size i = 0; i != DIM; ++i)
1109  result[i] = abs( v[i]);
1110  return result;
1111 }
1112 
1114 template <typename T, Size DIM>
1116 {
1117  Vector<T,DIM> result;
1118  for( Size i = 0; i != DIM; ++i)
1119  result[i] = acos( v[i]);
1120  return result;
1121 }
1122 
1124 template <typename T, Size DIM>
1125 inline bool all( const Vector<T,DIM>& v)
1126 {
1127  for( Size i = 0; i != DIM; ++i)
1128  if( !all(v[i]))
1129  return false;
1130  return true;
1131 }
1132 
1134 template <typename T, Size DIM>
1135 inline bool any( const Vector<T,DIM>& v)
1136 {
1137  for( Size i = 0; i != DIM; ++i)
1138  if( any(v[i]))
1139  return true;
1140  return false;
1141 }
1142 
1144 template <typename T, Size DIM>
1146 {
1147  Vector<T,DIM> result;
1148  for( Size i = 0; i != DIM; ++i)
1149  result[i] = asin( v[i]);
1150  return result;
1151 }
1152 
1154 template <typename T, Size DIM>
1156 {
1157  Vector<T,DIM> result;
1158  for( Size i = 0; i != DIM; ++i)
1159  result[i] = atan( v[i]);
1160  return result;
1161 }
1162 
1166 template <typename T, Size DIM>
1167 inline Vector<T,DIM> atan2( const Vector<T,DIM>& v, const Vector<T,DIM>& w)
1168 {
1169  Vector<T,DIM> result;
1170  for( Size i = 0; i != DIM; ++i)
1171  result[i] = atan2( v[i], w[i]);
1172  return result;
1173 }
1174 
1177 template <typename T, Size DIM>
1179 {
1180  Vector<T,DIM> result;
1181  for( Size i = 0; i != DIM; ++i)
1182  result[i] = ceil( v[i]);
1183  return result;
1184 }
1185 
1187 template <typename T, Size DIM>
1189  const Vector<T,DIM>& v,
1190  const Vector<T,DIM>& low,
1191  const Vector<T,DIM>& high)
1192 {
1193  Vector<T,DIM> result;
1194  for( Size i = 0u; i < DIM; ++i)
1195  result[i] = clamp( v[i], low[i], high[i]);
1196  return result;
1197 }
1198 
1200 template <typename T, Size DIM>
1202  const Vector<T,DIM>& v,
1203  const Vector<T,DIM>& low,
1204  T high)
1205 {
1206  Vector<T,DIM> result;
1207  for( Size i = 0u; i < DIM; ++i)
1208  result[i] = clamp( v[i], low[i], high);
1209  return result;
1210 }
1211 
1213 template <typename T, Size DIM>
1215  const Vector<T,DIM>& v,
1216  T low,
1217  const Vector<T,DIM>& high)
1218 {
1219  Vector<T,DIM> result;
1220  for( Size i = 0u; i < DIM; ++i)
1221  result[i] = clamp( v[i], low, high[i]);
1222  return result;
1223 }
1224 
1226 template <typename T, Size DIM>
1228  const Vector<T,DIM>& v,
1229  T low,
1230  T high)
1231 {
1232  Vector<T,DIM> result;
1233  for( Size i = 0u; i < DIM; ++i)
1234  result[i] = clamp( v[i], low, high);
1235  return result;
1236 }
1237 
1239 template <typename T, Size DIM>
1241 {
1242  Vector<T,DIM> result;
1243  for( Size i = 0; i != DIM; ++i)
1244  result[i] = cos( v[i]);
1245  return result;
1246 }
1247 
1249 template <typename T, Size DIM>
1251 {
1252  Vector<T,DIM> result;
1253  for( Size i = 0; i != DIM; ++i)
1254  result[i] = degrees( v[i]);
1255  return result;
1256 }
1257 
1259 template <typename T, Size DIM>
1261  const Vector<T,DIM>& lhs,
1262  const Vector<T,DIM>& rhs)
1263 {
1264  Vector<T,DIM> r;
1265  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1266  r[i] = base::max MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1267  return r;
1268 }
1269 
1271 template <typename T, Size DIM>
1273  const Vector<T,DIM>& lhs,
1274  const Vector<T,DIM>& rhs)
1275 {
1276  Vector<T,DIM> r;
1277  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1278  r[i] = base::min MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1279  return r;
1280 }
1281 
1283 template <typename T, Size DIM>
1285 {
1286  Vector<T,DIM> result;
1287  for( Size i = 0; i != DIM; ++i)
1288  result[i] = exp( v[i]);
1289  return result;
1290 }
1291 
1293 template <typename T, Size DIM>
1295 {
1296  Vector<T,DIM> result;
1297  for( Size i = 0; i != DIM; ++i)
1298  result[i] = exp2( v[i]);
1299  return result;
1300 }
1301 
1304 template <typename T, Size DIM>
1306 {
1307  Vector<T,DIM> result;
1308  for( Size i = 0; i != DIM; ++i)
1309  result[i] = floor( v[i]);
1310  return result;
1311 }
1312 
1316 template <typename T, Size DIM>
1317 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1318 {
1319  Vector<T,DIM> result;
1320  for( Size i = 0; i != DIM; ++i)
1321  result[i] = fmod( a[i], b[i]);
1322  return result;
1323 }
1324 
1328 template <typename T, Size DIM>
1329 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, T b)
1330 {
1331  Vector<T,DIM> result;
1332  for( Size i = 0; i != DIM; ++i)
1333  result[i] = fmod( a[i], b);
1334  return result;
1335 }
1336 
1338 template <typename T, Size DIM>
1340 {
1341  Vector<T,DIM> result;
1342  for( Size i = 0; i != DIM; ++i)
1343  result[i] = frac( v[i]);
1344  return result;
1345 }
1346 
1348 template <typename T, Size DIM>
1349 inline bool is_approx_equal(
1350  const Vector<T,DIM>& left,
1351  const Vector<T,DIM>& right,
1352  T e)
1353 {
1354  for( Size i = 0u; i < DIM; ++i)
1355  if( !is_approx_equal( left[i], right[i], e))
1356  return false;
1357  return true;
1358 }
1359 
1362 template <typename T, Size DIM>
1364  const Vector<T,DIM>& v1,
1365  const Vector<T,DIM>& v2,
1366  const Vector<T,DIM>& t)
1367 {
1368  Vector<T,DIM> result;
1369  for( Size i = 0; i != DIM; ++i)
1370  result[i] = v1[i] * (T(1)-t[i]) + v2[i] * t[i];
1371  return result;
1372 }
1373 
1376 template <typename T, Size DIM>
1378  const Vector<T,DIM>& v1,
1379  const Vector<T,DIM>& v2,
1380  T t)
1381 {
1382  // equivalent to: return v1 * (T(1)-t) + v2 * t;
1383  Vector<T,DIM> result;
1384  T t2 = T(1) - t;
1385  for( Size i = 0; i != DIM; ++i)
1386  result[i] = v1[i] * t2 + v2[i] * t;
1387  return result;
1388 }
1389 
1391 template <typename T, Size DIM>
1393 {
1394  Vector<T,DIM> result;
1395  for( Size i = 0; i != DIM; ++i)
1396  result[i] = log( v[i]);
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] = log2 MI_PREVENT_MACRO_EXPAND ( v[i]);
1407  return result;
1408 }
1409 
1411 template <typename T, Size DIM>
1413 {
1414  Vector<T,DIM> result;
1415  for( Size i = 0; i != DIM; ++i)
1416  result[i] = log10( v[i]);
1417  return result;
1418 }
1419 
1424 template <typename T, Size DIM>
1426 {
1427  Vector<T,DIM> result;
1428  for( Size j = 0; j != DIM; ++j)
1429  result[j] = modf( v[j], i[j]);
1430  return result;
1431 }
1432 
1434 template <typename T, Size DIM>
1435 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1436 {
1437  Vector<T,DIM> result;
1438  for( Size i = 0; i != DIM; ++i)
1439  result[i] = pow( a[i], b[i]);
1440  return result;
1441 }
1442 
1444 template <typename T, Size DIM>
1445 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, T b)
1446 {
1447  Vector<T,DIM> result;
1448  for( Size i = 0; i != DIM; ++i)
1449  result[i] = pow( a[i], b);
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] = radians( 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] = round( 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] = rsqrt( v[i]);
1480  return result;
1481 }
1482 
1484 template <typename T, Size DIM>
1486 {
1487  Vector<T,DIM> result;
1488  for( Size i = 0; i != DIM; ++i)
1489  result[i] = saturate( v[i]);
1490  return result;
1491 }
1492 
1494 template <typename T, Size DIM>
1496 {
1497  Vector<T,DIM> result;
1498  for( Size i = 0; i != DIM; ++i)
1499  result[i] = sign( v[i]);
1500  return result;
1501 }
1502 
1504 template <typename T, Size DIM>
1506 {
1507  Vector<T,DIM> result;
1508  for( Size i = 0; i != DIM; ++i)
1509  result[i] = sin( v[i]);
1510  return result;
1511 }
1512 
1516 template <typename T, Size DIM>
1517 inline void sincos( const Vector<T,DIM>& a, Vector<T,DIM>& s, Vector<T,DIM>& c)
1518 {
1519  for( Size i = 0; i != DIM; ++i)
1520  sincos( a[i], s[i], c[i]);
1521 }
1522 
1528 template <typename T, Size DIM>
1530  const Vector<T,DIM>& a,
1531  const Vector<T,DIM>& b,
1532  const Vector<T,DIM>& v)
1533 {
1534  Vector<T,DIM> result;
1535  for( Size i = 0; i != DIM; ++i)
1536  result[i] = smoothstep( a[i], b[i], v[i]);
1537  return result;
1538 }
1539 
1545 template <typename T, Size DIM>
1547  const Vector<T,DIM>& a,
1548  const Vector<T,DIM>& b,
1549  T x)
1550 {
1551  Vector<T,DIM> result;
1552  for( Size i = 0; i != DIM; ++i)
1553  result[i] = smoothstep( a[i], b[i], x);
1554  return result;
1555 }
1556 
1558 template <typename T, Size DIM>
1560 {
1561  Vector<T,DIM> result;
1562  for( Size i = 0; i != DIM; ++i)
1563  result[i] = sqrt( v[i]);
1564  return result;
1565 }
1566 
1568 template <typename T, Size DIM>
1569 inline Vector<T,DIM> step( const Vector<T,DIM>& a, const Vector<T,DIM>& v)
1570 {
1571  Vector<T,DIM> result;
1572  for( Size i = 0; i != DIM; ++i)
1573  result[i] = step( a[i], v[i]);
1574  return result;
1575 }
1576 
1578 template <typename T, Size DIM>
1580 {
1581  Vector<T,DIM> result;
1582  for( Size i = 0; i != DIM; ++i)
1583  result[i] = tan( v[i]);
1584  return result;
1585 }
1586 
1587 
1588 //------ Geometric Vector Algorithms ------------------------------------------
1589 
1591 template <typename T>
1592 inline T cross(
1593  const Vector<T,2>& lhs,
1594  const Vector<T,2>& rhs)
1595 {
1596  return lhs.x * rhs.y - lhs.y * rhs.x;
1597 }
1598 
1600 template <typename T>
1602  const Vector<T,3>& lhs,
1603  const Vector<T,3>& rhs)
1604 {
1605  return Vector<T,3>( lhs.y * rhs.z - lhs.z * rhs.y,
1606  lhs.z * rhs.x - lhs.x * rhs.z,
1607  lhs.x * rhs.y - lhs.y * rhs.x);
1608 }
1609 
1615 template <typename T>
1616 inline void make_basis(
1617  const Vector<T,3>& n,
1618  Vector<T,3>* u,
1619  Vector<T,3>* v)
1620 {
1621 #ifdef mi_base_assert_enabled
1622  const T eps = 1e-6f; // smallest resolvable factor
1623 #endif
1624 
1625  mi_math_assert_msg( u != 0, "precondition");
1626  mi_math_assert_msg( v != 0, "precondition");
1627  // Sanity check: the normal vector must be unit length.
1628  mi_math_assert_msg( abs( length(n) - 1.0f) < eps, "precondition");
1629 
1630  // Compute u.
1631  if( abs(n.x) < abs(n.y)) {
1632  // u = cross(x, n), x = (1, 0, 0)
1633  u->x = T(0);
1634  u->y = -n.z;
1635  u->z = n.y;
1636  } else {
1637  // u = cross(y, n), y = (0, 1, 0)
1638  u->x = n.z;
1639  u->y = T(0);
1640  u->z = -n.x;
1641  }
1642  u->normalize();
1643 
1644  // Compute v. Since *u and n are orthogonal and unit-length,
1645  // there is no need to normalize *v.
1646  *v = cross( *u, n);
1647 
1648  // Sanity check: make sure (u, n, v) is an orthogonal basis.
1649  mi_math_assert_msg( abs( dot( *u, n)) < eps, "postcondition");
1650  mi_math_assert_msg( abs( dot( *u, *v)) < eps, "postcondition");
1651  mi_math_assert_msg( abs( dot( n, *v)) < eps, "postcondition");
1652  // Sanity check: make sure u and v are unit length.
1653  mi_math_assert_msg( abs( length( *u) - T(1)) < eps, "postcondition");
1654  mi_math_assert_msg( abs( length( *v) - T(1)) < eps, "postcondition");
1655 }
1656 
1663 template <typename T>
1664 inline void make_basis(
1665  const Vector<T,3>& n,
1666  const Vector<T,3>& u,
1667  const Vector<T,3>& v,
1668  Vector<T,3>* t,
1669  Vector<T,3>* b)
1670 {
1671  const T eps = 1e-6f; // smallest resolvable factor
1672  (void)eps;
1673 
1674  mi_math_assert_msg( t != 0, "precondition");
1675  mi_math_assert_msg( b != 0, "precondition");
1676  // Sanity check: the normal vector must be unit length.
1677  mi_math_assert_msg( abs( length( n) - 1.0f) < eps, "precondition");
1678  // Sanity check: the other vector lengths should be finite and non-zero
1679  mi_math_assert_msg( length( u) > 0., "precondition");
1680  mi_math_assert_msg( length( v) > 0., "precondition");
1681  mi_math_assert_msg( isfinite( length( u)), "precondition");
1682  mi_math_assert_msg( isfinite( length( v)), "precondition");
1683 
1684  // Compute b
1685  *b = cross(u,n);
1686  b->normalize();
1687 
1688  // Compute t. Since *b and n are orthogonal and unit-length,
1689  // there is no need to normalize *t.
1690  *t = cross(n,*b);
1691 
1692  // Check that b has the same orientation of v
1693  if( dot( *b,v) < T(0))
1694  *b = -*b;
1695 
1696  // Sanity check: make sure *u and t have the same orientation.
1697  mi_math_assert_msg( dot( u, *t) > T(0), "postcondition");
1698  // Sanity check: make sure (t, n, b) is an orthogonal basis.
1699  // We use a scaled epsilon in order to avoid false positives.
1700  mi_math_assert_msg( abs( dot( *t, n)) < 20*eps, "postcondition");
1701  mi_math_assert_msg( abs( dot( *t, *b)) < 20*eps, "postcondition");
1702  mi_math_assert_msg( abs( dot( n, *b)) < 20*eps, "postcondition");
1703  // Sanity check: make sure t and b are unit length.
1704  mi_math_assert_msg( abs( length( *t) - T(1)) < eps, "postcondition");
1705  mi_math_assert_msg( abs( length( *b) - T(1)) < eps, "postcondition");
1706 }
1707 
1713 template <typename T2, Size DIM2, typename T1, Size DIM1>
1715  const Vector<T1, DIM1>& v,
1716  const T2& fill = T2(0))
1717 {
1718  const Size dim_min = base::min MI_PREVENT_MACRO_EXPAND ( DIM1, DIM2 );
1719  Vector<T2, DIM2> result;
1720  for( Size i = 0; i < dim_min; ++i)
1721  result[i] = T2(v[i]);
1722  for( Size i = dim_min; i < DIM2; ++i)
1723  result[i] = fill;
1724  return result;
1725 }
1726  // end group mi_math_vector
1728 
1729 } // namespace math
1730 
1731 } // namespace mi
1732 
1733 #endif // MI_MATH_VECTOR_H