Material Definition Language 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 2020 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 
248 template < class T, Size DIM>
249 class Vector;
250 // Using a proxy class to make comparison operators a lesser match when it comes
251 // to an overload resolution set with the MetaSL definitions of these operators.
252 template <typename T, Size DIM>
253 struct Vector_proxy_ //-V690 PVS
254 {
255  const Vector<T,DIM>& vec;
256  Vector_proxy_( const Vector<T,DIM>& v) : vec( v) { }
257 private:
259  Vector_proxy_& operator=( const Vector_proxy_& o);
260 };
261 
262 
263 
300 template < class T, Size DIM>
301 class Vector : public Vector_struct<T, DIM> //-V690 PVS
302 {
303 public:
306 
307  typedef T value_type;
308  typedef Size size_type;
310  typedef T * pointer;
311  typedef const T * const_pointer;
312  typedef T & reference;
313  typedef const T & const_reference;
314 
315  static const Size DIMENSION = DIM;
316  static const Size SIZE = DIM;
317 
319  static inline Size size() { return SIZE; }
320 
322  static inline Size max_size() { return SIZE; }
323 
325  inline T* begin() { return mi::math::vector_base_ptr( *this); }
326 
328  inline const T* begin() const { return mi::math::vector_base_ptr( *this); }
329 
333  inline T* end() { return begin() + DIM; }
334 
338  inline const T* end() const { return begin() + DIM; }
339 
341  inline Vector()
342  {
343 #if defined(DEBUG) || (defined(_MSC_VER) && _MSC_VER <= 1310)
344  // In debug mode, default-constructed vectors are initialized with signaling NaNs or, if not
345  // applicable, with a maximum value to increase the chances of diagnosing incorrect use of
346  // an uninitialized vector.
347  //
348  // When compiling with Visual C++ 7.1 or earlier, this code is enabled in all variants to
349  // work around a very obscure compiler bug that causes the compiler to crash.
350  typedef mi::base::numeric_traits<T> Traits;
351  T v = (Traits::has_signaling_NaN) ? Traits::signaling_NaN()
352  : Traits::max MI_PREVENT_MACRO_EXPAND ();
353  for( Size i(0u); i < DIM; ++i)
354  (*this)[i] = v;
355 #endif
356  }
357 
359  inline Vector( const Vector_struct<T,DIM>& vec )
360  {
361  for( Size i(0u); i < DIM; ++i)
362  (*this)[i] = mi::math::vector_base_ptr(vec)[i];
363  }
364 
366  inline explicit Vector(T v)
367  {
368  for( Size i(0u); i < DIM; ++i)
369  (*this)[i] = v;
370  }
371 
385  template <typename Iterator>
386  inline Vector(From_iterator_tag, Iterator p)
387  {
388  for( Size i(0u); i < DIM; ++i, ++p)
389  (*this)[i] = *p;
390  }
391 
403  template <typename T2>
404  inline explicit Vector( T2 const (& array)[DIM])
405  {
406  for( Size i(0u); i < DIM; ++i)
407  (*this)[i] = array[i];
408  }
409 
412  template <typename T2>
413  inline explicit Vector( const Vector<T2,DIM>& other)
414  {
415  for( Size i(0u); i < DIM; ++i)
416  (*this)[i] = T(other[i]);
417  }
418 
421  template <typename T2>
422  inline explicit Vector( const Vector_struct<T2,DIM>& other)
423  {
424  for( Size i(0u); i < DIM; ++i)
425  (*this)[i] = T(mi::math::vector_base_ptr(other)[i]);
426  }
427 
432  inline Vector(T v1, T v2)
433  {
434  mi_static_assert(DIM == 2);
435  begin()[0] = v1;
436  begin()[1] = v2;
437  }
438 
443  inline Vector(T v1, T v2, T v3)
444  {
445  mi_static_assert(DIM == 3);
446  begin()[0] = v1;
447  begin()[1] = v2;
448  begin()[2] = v3;
449  }
450 
455  inline Vector(T v1, const Vector<T,2>& v2)
456  {
457  mi_static_assert(DIM == 3);
458  begin()[0] = v1;
459  begin()[1] = v2.x;
460  begin()[2] = v2.y;
461  }
462 
467  inline Vector(const Vector<T,2>& v1, T v2)
468  {
469  mi_static_assert(DIM == 3);
470  begin()[0] = v1.x;
471  begin()[1] = v1.y;
472  begin()[2] = v2;
473  }
474 
479  inline Vector(T v1, T v2, T v3, T v4)
480  {
481  mi_static_assert(DIM == 4);
482  begin()[0] = v1;
483  begin()[1] = v2;
484  begin()[2] = v3;
485  begin()[3] = v4;
486  }
487 
492  inline Vector(T v1, T v2, const Vector<T,2>& v3)
493  {
494  mi_static_assert(DIM == 4);
495  begin()[0] = v1;
496  begin()[1] = v2;
497  begin()[2] = v3.x;
498  begin()[3] = v3.y;
499  }
500 
501 
506  inline Vector(T v1, const Vector<T,2>& v2, T v3)
507  {
508  mi_static_assert(DIM == 4);
509  begin()[0] = v1;
510  begin()[1] = v2.x;
511  begin()[2] = v2.y;
512  begin()[3] = v3;
513  }
514 
519  inline Vector(const Vector<T,2>& v1, T v2, T v3)
520  {
521  mi_static_assert(DIM == 4);
522  begin()[0] = v1.x;
523  begin()[1] = v1.y;
524  begin()[2] = v2;
525  begin()[3] = v3;
526  }
527 
532  inline Vector(const Vector<T,2>& v1, const Vector<T,2>& v2)
533  {
534  mi_static_assert(DIM == 4);
535  begin()[0] = v1.x;
536  begin()[1] = v1.y;
537  begin()[2] = v2.x;
538  begin()[3] = v2.y;
539  }
540 
545  inline Vector(T v1, const Vector<T,3>& v2)
546  {
547  mi_static_assert(DIM == 4);
548  begin()[0] = v1;
549  begin()[1] = v2.x;
550  begin()[2] = v2.y;
551  begin()[3] = v2.z;
552  }
553 
558  inline Vector(const Vector<T,3>& v1, T v2)
559  {
560  mi_static_assert(DIM == 4);
561  begin()[0] = v1.x;
562  begin()[1] = v1.y;
563  begin()[2] = v1.z;
564  begin()[3] = v2;
565  }
566 
571  inline explicit Vector( const Color_struct& color)
572  {
573  mi_static_assert(DIM == 4);
574  this->x = color.r;
575  this->y = color.g;
576  this->z = color.b;
577  this->w = color.a;
578  }
579 
581  inline Vector& operator= ( const Vector& other)
582  {
583  for( Size i(0u); i < DIM; ++i)
584  (*this)[i] = other[i];
585  return *this;
586  }
587 
589  inline Vector& operator= ( T s)
590  {
591  for( Size i(0u); i < DIM; ++i)
592  (*this)[i] = s;
593  return *this;
594  }
599  inline Vector& operator= ( const Color_struct& color)
600  {
601  mi_static_assert(DIM == 4);
602  this->x = color.r;
603  this->y = color.g;
604  this->z = color.b;
605  this->w = color.a;
606  return *this;
607  }
608 
612  inline T& operator[] (Size i)
613  {
614  mi_math_assert_msg(i < DIM, "precondition");
615  return begin()[i];
616  }
617 
621  inline const T& operator[] (Size i) const
622  {
623  mi_math_assert_msg(i < DIM, "precondition");
624  return begin()[i];
625  }
626 
630  inline const T& get(Size i) const
631  {
632  mi_math_assert_msg(i < DIM, "precondition");
633  return begin()[i];
634  }
635 
639  inline void set(Size i, T value)
640  {
641  mi_math_assert_msg(i < DIM, "precondition");
642  begin()[i] = value;
643  }
644 
645 
646 
653  inline bool normalize()
654  {
655  const T rec_length = T(1) / length( *this);
656  const bool result = isfinite( rec_length);
657  if( result)
658  (*this) *= rec_length;
659  return result;
660  }
661 
662 
663  //------ Free comparison operators ==, !=, <, <=, >, >= for vectors --------
664  // Using a proxy class to make comparison operators a lesser match when it comes
665  // to an overload resolution set with the MetaSL definitions of these operators.
666 
668  inline bool operator==( Vector_proxy_<T,DIM> rhs) const
669  {
670  return is_equal( *this, rhs.vec);
671  }
672 
674  inline bool operator!=( Vector_proxy_<T,DIM> rhs) const
675  {
676  return is_not_equal( *this, rhs.vec);
677  }
678 
682  inline bool operator<( Vector_proxy_<T,DIM> rhs) const
683  {
684  return lexicographically_less( *this, rhs.vec);
685  }
686 
690  inline bool operator<=( Vector_proxy_<T,DIM> rhs) const
691  {
692  return lexicographically_less_or_equal( *this, rhs.vec);
693  }
694 
698  inline bool operator>( Vector_proxy_<T,DIM> rhs) const
699  {
700  return lexicographically_greater( *this, rhs.vec);
701  }
702 
706  inline bool operator>=( Vector_proxy_<T,DIM> rhs) const
707  {
708  return lexicographically_greater_or_equal( *this, rhs.vec);
709  }
710 };
711 
712 
713 //------ Free operators +=, -=, *=, /=, +, -, *, and / for vectors -------------
714 
716 template <typename T, Size DIM>
718  Vector<T,DIM>& lhs,
719  const Vector<T,DIM>& rhs)
720 {
721  for( Size i(0u); i < DIM; ++i)
722  lhs[i] += rhs[i];
723  return lhs;
724 }
725 
727 template <typename T, Size DIM>
729  Vector<T,DIM>& lhs,
730  const Vector<T,DIM>& rhs)
731 {
732  for( Size i(0u); i < DIM; ++i)
733  lhs[i] -= rhs[i];
734  return lhs;
735 }
736 
738 template <typename T, Size DIM>
740  Vector<T,DIM>& lhs,
741  const Vector<T,DIM>& rhs)
742 {
743  for( Size i(0u); i < DIM; ++i)
744  lhs[i] *= rhs[i];
745  return lhs;
746 }
747 
750 template <typename T, Size DIM>
752  Vector<T,DIM>& lhs,
753  const Vector<T,DIM>& rhs)
754 {
755  for( Size i(0u); i < DIM; ++i)
756  lhs[i] %= rhs[i];
757  return lhs;
758 }
759 
761 template <typename T, typename U, Size DIM>
763  Vector<T,DIM>& lhs,
764  const Vector<U,DIM>& rhs)
765 {
766  for( Size i(0u); i < DIM; ++i)
767  lhs[i] = T(lhs[i] / rhs[i]);
768  return lhs;
769 }
770 
772 template <typename T, Size DIM>
774  const Vector<T,DIM>& lhs,
775  const Vector<T,DIM>& rhs)
776 {
777  Vector<T,DIM> tmp( lhs);
778  return tmp += rhs;
779 }
780 
782 template <typename T, Size DIM>
784  const Vector<T,DIM>& lhs,
785  const Vector<T,DIM>& rhs)
786 {
787  Vector<T,DIM> tmp( lhs);
788  return tmp -= rhs;
789 }
790 
792 template <typename T, Size DIM>
794  const Vector<T,DIM>& lhs,
795  const Vector<T,DIM>& rhs)
796 {
797  Vector<T,DIM> tmp( lhs);
798  return tmp *= rhs;
799 }
800 
803 template <typename T, Size DIM>
805  const Vector<T,DIM>& lhs,
806  const Vector<T,DIM>& rhs)
807 {
808  Vector<T,DIM> tmp( lhs);
809  return tmp %= rhs;
810 }
811 
813 template <typename T, typename U, Size DIM>
815  const Vector<T,DIM>& lhs,
816  const Vector<U,DIM>& rhs)
817 {
818  Vector<T,DIM> tmp(lhs);
819  return tmp /= rhs;
820 }
821 
823 template <typename T, Size DIM>
825 {
826  Vector<T,DIM> tmp;
827  for( Size i(0u); i < DIM; ++i)
828  tmp[i] = -v[i];
829  return tmp;
830 }
831 
832 
833 //------ Free operator *=, /=, *, and / definitions for scalars ---------------
834 
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 
850 template <typename T, typename TT, Size DIM>
852  Vector<T,DIM>& v,
853  TT s)
854 {
855  for( Size i(0u); i < DIM; ++i)
856  v[i] = T(v[i] % s);
857  return v;
858 }
859 
861 template <typename T, typename TT, Size DIM>
863  Vector<T,DIM>& v,
864  TT s)
865 {
866  for( Size i(0u); i < DIM; ++i)
867  v[i] = T(v[i] / s);
868  return v;
869 }
870 
872 template <typename T, typename TT, Size DIM>
874  const Vector<T,DIM>& v,
875  TT s)
876 {
877  Vector<T,DIM> tmp( v);
878  return tmp *= s;
879 }
880 
882 template <typename T, typename TT, Size DIM>
884  TT s,
885  const Vector<T,DIM>& v)
886 {
887  Vector<T,DIM> tmp(v);
888  return tmp *= s;
889 }
890 
894 template <typename T, typename TT, Size DIM>
896  const Vector<T,DIM>& v,
897  TT s)
898 {
899  Vector<T,DIM> tmp(v);
900  return tmp %= s;
901 }
902 
904 template <typename T, typename TT, Size DIM>
906  const Vector<T,DIM>& v,
907  TT s)
908 {
909  Vector<T,DIM> tmp( v);
910  return tmp /= s;
911 }
912 
913 
914 //------ Free operator ++, -- for vectors -------------------------------------
915 
917 template <typename T, Size DIM>
919 {
921  return vec;
922 }
923 
925 template <typename T, Size DIM>
927 {
929  return vec;
930 }
931 
932 
933 //------ Free operators !, &&, ||, ^ for bool vectors and bool scalars ---------
934 
936 template <Size DIM>
938  const Vector<bool,DIM>& lhs,
939  const Vector<bool,DIM>& rhs)
940 {
941  Vector<bool,DIM> result;
942  general::transform( lhs, rhs, result, functor::Operator_and_and());
943  return result;
944 }
945 
947 template <Size DIM>
949  bool lhs,
950  const Vector<bool,DIM>& rhs)
951 {
952  Vector<bool,DIM> result;
954  return result;
955 }
956 
958 template <Size DIM>
960  const Vector<bool,DIM>& lhs,
961  bool rhs)
962 {
963  Vector<bool,DIM> result;
965  return result;
966 }
967 
969 template <Size DIM>
971  const Vector<bool,DIM>& lhs,
972  const Vector<bool,DIM>& rhs)
973 {
974  Vector<bool,DIM> result;
975  general::transform(lhs, rhs, result, functor::Operator_or_or());
976  return result;
977 }
978 
980 template <Size DIM>
982  bool lhs,
983  const Vector<bool,DIM>& rhs)
984 {
985  Vector<bool,DIM> result;
987  return result;
988 }
989 
991 template <Size DIM>
993  const Vector<bool,DIM>& lhs,
994  bool rhs)
995 {
996  Vector<bool,DIM> result;
998  return result;
999 }
1000 
1002 template <Size DIM>
1004  const Vector<bool,DIM>& lhs,
1005  const Vector<bool,DIM>& rhs)
1006 {
1007  Vector<bool,DIM> result;
1008  general::transform( lhs, rhs, result, functor::Operator_xor());
1009  return result;
1010 }
1011 
1013 template <Size DIM>
1015  bool lhs,
1016  const Vector<bool,DIM>& rhs)
1017 {
1018  Vector<bool,DIM> result;
1020  return result;
1021 }
1022 
1024 template <Size DIM>
1026  const Vector<bool,DIM>& lhs,
1027  bool rhs)
1028 {
1029  Vector<bool,DIM> result;
1031  return result;
1032 }
1033 
1035 template <Size DIM>
1037  const Vector<bool,DIM>& vec)
1038 {
1039  Vector<bool,DIM> result;
1040  general::transform( vec, result, functor::Operator_not());
1041  return result;
1042 }
1043 
1044 
1045 //------ Elementwise comparison operators returning a bool vector. ------------
1046 
1048 template <typename T, Size DIM>
1050  const Vector<T,DIM>& lhs,
1051  const Vector<T,DIM>& rhs)
1052 {
1053  Vector<bool,DIM> result;
1055  return result;
1056 }
1057 
1059 template <typename T, Size DIM>
1061  const Vector<T,DIM>& lhs,
1062  const Vector<T,DIM>& rhs)
1063 {
1064  Vector<bool,DIM> result;
1065  general::transform( lhs, rhs, result,functor::Operator_not_equal());
1066  return result;
1067 }
1068 
1070 template <typename T, Size DIM>
1072  const Vector<T,DIM>& lhs,
1073  const Vector<T,DIM>& rhs)
1074 {
1075  Vector<bool,DIM> result;
1076  general::transform( lhs, rhs, result,functor::Operator_less());
1077  return result;
1078 }
1079 
1081 template <typename T, Size DIM>
1083  const Vector<T,DIM>& lhs,
1084  const Vector<T,DIM>& rhs)
1085 {
1086  Vector<bool,DIM> result;
1087  general::transform( lhs, rhs, result,functor::Operator_less_equal());
1088  return result;
1089 }
1090 
1092 template <typename T, Size DIM>
1094  const Vector<T,DIM>& lhs,
1095  const Vector<T,DIM>& rhs)
1096 {
1097  Vector<bool,DIM> result;
1098  general::transform( lhs, rhs, result,functor::Operator_greater());
1099  return result;
1100 }
1101 
1103 template <typename T, Size DIM>
1105  const Vector<T,DIM>& lhs,
1106  const Vector<T,DIM>& rhs)
1107 {
1108  Vector<bool,DIM> result;
1110  return result;
1111 }
1112 
1113 
1114 //------ Function Overloads for Vector Algorithms -----------------------------
1115 
1117 template <typename T, Size DIM>
1119 {
1120  Vector<T,DIM> result;
1121  for( Size i = 0; i != DIM; ++i)
1122  result[i] = abs( v[i]);
1123  return result;
1124 }
1125 
1127 template <typename T, Size DIM>
1129 {
1130  Vector<T,DIM> result;
1131  for( Size i = 0; i != DIM; ++i)
1132  result[i] = acos( v[i]);
1133  return result;
1134 }
1135 
1137 template <typename T, Size DIM>
1138 inline bool all( const Vector<T,DIM>& v)
1139 {
1140  for( Size i = 0; i != DIM; ++i)
1141  if( !all(v[i]))
1142  return false;
1143  return true;
1144 }
1145 
1147 template <typename T, Size DIM>
1148 inline bool any( const Vector<T,DIM>& v)
1149 {
1150  for( Size i = 0; i != DIM; ++i)
1151  if( any(v[i]))
1152  return true;
1153  return false;
1154 }
1155 
1157 template <typename T, Size DIM>
1159 {
1160  Vector<T,DIM> result;
1161  for( Size i = 0; i != DIM; ++i)
1162  result[i] = asin( v[i]);
1163  return result;
1164 }
1165 
1167 template <typename T, Size DIM>
1169 {
1170  Vector<T,DIM> result;
1171  for( Size i = 0; i != DIM; ++i)
1172  result[i] = atan( v[i]);
1173  return result;
1174 }
1175 
1179 template <typename T, Size DIM>
1180 inline Vector<T,DIM> atan2( const Vector<T,DIM>& v, const Vector<T,DIM>& w)
1181 {
1182  Vector<T,DIM> result;
1183  for( Size i = 0; i != DIM; ++i)
1184  result[i] = atan2( v[i], w[i]);
1185  return result;
1186 }
1187 
1190 template <typename T, Size DIM>
1192 {
1193  Vector<T,DIM> result;
1194  for( Size i = 0; i != DIM; ++i)
1195  result[i] = ceil( v[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  const Vector<T,DIM>& high)
1205 {
1206  Vector<T,DIM> result;
1207  for( Size i = 0u; i < DIM; ++i)
1208  result[i] = clamp( v[i], low[i], high[i]);
1209  return result;
1210 }
1211 
1213 template <typename T, Size DIM>
1215  const Vector<T,DIM>& v,
1216  const Vector<T,DIM>& low,
1217  T high)
1218 {
1219  Vector<T,DIM> result;
1220  for( Size i = 0u; i < DIM; ++i)
1221  result[i] = clamp( v[i], low[i], high);
1222  return result;
1223 }
1224 
1226 template <typename T, Size DIM>
1228  const Vector<T,DIM>& v,
1229  T low,
1230  const Vector<T,DIM>& high)
1231 {
1232  Vector<T,DIM> result;
1233  for( Size i = 0u; i < DIM; ++i)
1234  result[i] = clamp( v[i], low, high[i]);
1235  return result;
1236 }
1237 
1239 template <typename T, Size DIM>
1241  const Vector<T,DIM>& v,
1242  T low,
1243  T high)
1244 {
1245  Vector<T,DIM> result;
1246  for( Size i = 0u; i < DIM; ++i)
1247  result[i] = clamp( v[i], low, high);
1248  return result;
1249 }
1250 
1252 template <typename T, Size DIM>
1254 {
1255  Vector<T,DIM> result;
1256  for( Size i = 0; i != DIM; ++i)
1257  result[i] = cos( v[i]);
1258  return result;
1259 }
1260 
1262 template <typename T, Size DIM>
1264 {
1265  Vector<T,DIM> result;
1266  for( Size i = 0; i != DIM; ++i)
1267  result[i] = degrees( v[i]);
1268  return result;
1269 }
1270 
1272 template <typename T, Size DIM>
1274  const Vector<T,DIM>& lhs,
1275  const Vector<T,DIM>& rhs)
1276 {
1277  Vector<T,DIM> r;
1278  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1279  r[i] = base::max MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1280  return r;
1281 }
1282 
1284 template <typename T, Size DIM>
1286  const Vector<T,DIM>& lhs,
1287  const Vector<T,DIM>& rhs)
1288 {
1289  Vector<T,DIM> r;
1290  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1291  r[i] = base::min MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1292  return r;
1293 }
1294 
1296 template <typename T, Size DIM>
1298 {
1299  Vector<T,DIM> result;
1300  for( Size i = 0; i != DIM; ++i)
1301  result[i] = exp( v[i]);
1302  return result;
1303 }
1304 
1306 template <typename T, Size DIM>
1308 {
1309  Vector<T,DIM> result;
1310  for( Size i = 0; i != DIM; ++i)
1311  result[i] = exp2( v[i]);
1312  return result;
1313 }
1314 
1317 template <typename T, Size DIM>
1319 {
1320  Vector<T,DIM> result;
1321  for( Size i = 0; i != DIM; ++i)
1322  result[i] = floor( v[i]);
1323  return result;
1324 }
1325 
1329 template <typename T, Size DIM>
1330 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1331 {
1332  Vector<T,DIM> result;
1333  for( Size i = 0; i != DIM; ++i)
1334  result[i] = fmod( a[i], b[i]);
1335  return result;
1336 }
1337 
1341 template <typename T, Size DIM>
1342 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, T b)
1343 {
1344  Vector<T,DIM> result;
1345  for( Size i = 0; i != DIM; ++i)
1346  result[i] = fmod( a[i], b);
1347  return result;
1348 }
1349 
1351 template <typename T, Size DIM>
1353 {
1354  Vector<T,DIM> result;
1355  for( Size i = 0; i != DIM; ++i)
1356  result[i] = frac( v[i]);
1357  return result;
1358 }
1359 
1361 template <typename T, Size DIM>
1362 inline bool is_approx_equal(
1363  const Vector<T,DIM>& left,
1364  const Vector<T,DIM>& right,
1365  T e)
1366 {
1367  for( Size i = 0u; i < DIM; ++i)
1368  if( !is_approx_equal( left[i], right[i], e))
1369  return false;
1370  return true;
1371 }
1372 
1375 template <typename T, Size DIM>
1377  const Vector<T,DIM>& v1,
1378  const Vector<T,DIM>& v2,
1379  const Vector<T,DIM>& t)
1380 {
1381  Vector<T,DIM> result;
1382  for( Size i = 0; i != DIM; ++i)
1383  result[i] = v1[i] * (T(1)-t[i]) + v2[i] * t[i];
1384  return result;
1385 }
1386 
1389 template <typename T, Size DIM>
1391  const Vector<T,DIM>& v1,
1392  const Vector<T,DIM>& v2,
1393  T t)
1394 {
1395  // equivalent to: return v1 * (T(1)-t) + v2 * t;
1396  Vector<T,DIM> result;
1397  T t2 = T(1) - t;
1398  for( Size i = 0; i != DIM; ++i)
1399  result[i] = v1[i] * t2 + v2[i] * t;
1400  return result;
1401 }
1402 
1404 template <typename T, Size DIM>
1406 {
1407  Vector<T,DIM> result;
1408  for( Size i = 0; i != DIM; ++i)
1409  result[i] = log( v[i]);
1410  return result;
1411 }
1412 
1414 template <typename T, Size DIM>
1416 {
1417  Vector<T,DIM> result;
1418  for( Size i = 0; i != DIM; ++i)
1419  result[i] = log2 MI_PREVENT_MACRO_EXPAND ( v[i]);
1420  return result;
1421 }
1422 
1424 template <typename T, Size DIM>
1426 {
1427  Vector<T,DIM> result;
1428  for( Size i = 0; i != DIM; ++i)
1429  result[i] = log10( v[i]);
1430  return result;
1431 }
1432 
1437 template <typename T, Size DIM>
1439 {
1440  Vector<T,DIM> result;
1441  for( Size j = 0; j != DIM; ++j)
1442  result[j] = modf( v[j], i[j]);
1443  return result;
1444 }
1445 
1447 template <typename T, Size DIM>
1448 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1449 {
1450  Vector<T,DIM> result;
1451  for( Size i = 0; i != DIM; ++i)
1452  result[i] = pow( a[i], b[i]);
1453  return result;
1454 }
1455 
1457 template <typename T, Size DIM>
1458 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, T b)
1459 {
1460  Vector<T,DIM> result;
1461  for( Size i = 0; i != DIM; ++i)
1462  result[i] = pow( a[i], b);
1463  return result;
1464 }
1465 
1467 template <typename T, Size DIM>
1469 {
1470  Vector<T,DIM> result;
1471  for( Size i = 0; i != DIM; ++i)
1472  result[i] = radians( v[i]);
1473  return result;
1474 }
1475 
1477 template <typename T, Size DIM>
1479 {
1480  Vector<T,DIM> result;
1481  for( Size i = 0; i != DIM; ++i)
1482  result[i] = round( v[i]);
1483  return result;
1484 }
1485 
1487 template <typename T, Size DIM>
1489 {
1490  Vector<T,DIM> result;
1491  for( Size i = 0; i != DIM; ++i)
1492  result[i] = rsqrt( v[i]);
1493  return result;
1494 }
1495 
1497 template <typename T, Size DIM>
1499 {
1500  Vector<T,DIM> result;
1501  for( Size i = 0; i != DIM; ++i)
1502  result[i] = saturate( v[i]);
1503  return result;
1504 }
1505 
1507 template <typename T, Size DIM>
1509 {
1510  Vector<T,DIM> result;
1511  for( Size i = 0; i != DIM; ++i)
1512  result[i] = sign( v[i]);
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] = sin( v[i]);
1523  return result;
1524 }
1525 
1529 template <typename T, Size DIM>
1530 inline void sincos( const Vector<T,DIM>& a, Vector<T,DIM>& s, Vector<T,DIM>& c)
1531 {
1532  for( Size i = 0; i != DIM; ++i)
1533  sincos( a[i], s[i], c[i]);
1534 }
1535 
1541 template <typename T, Size DIM>
1543  const Vector<T,DIM>& a,
1544  const Vector<T,DIM>& b,
1545  const Vector<T,DIM>& v)
1546 {
1547  Vector<T,DIM> result;
1548  for( Size i = 0; i != DIM; ++i)
1549  result[i] = smoothstep( a[i], b[i], v[i]);
1550  return result;
1551 }
1552 
1558 template <typename T, Size DIM>
1560  const Vector<T,DIM>& a,
1561  const Vector<T,DIM>& b,
1562  T x)
1563 {
1564  Vector<T,DIM> result;
1565  for( Size i = 0; i != DIM; ++i)
1566  result[i] = smoothstep( a[i], b[i], x);
1567  return result;
1568 }
1569 
1571 template <typename T, Size DIM>
1573 {
1574  Vector<T,DIM> result;
1575  for( Size i = 0; i != DIM; ++i)
1576  result[i] = sqrt( v[i]);
1577  return result;
1578 }
1579 
1581 template <typename T, Size DIM>
1582 inline Vector<T,DIM> step( const Vector<T,DIM>& a, const Vector<T,DIM>& v)
1583 {
1584  Vector<T,DIM> result;
1585  for( Size i = 0; i != DIM; ++i)
1586  result[i] = step( a[i], v[i]);
1587  return result;
1588 }
1589 
1591 template <typename T, Size DIM>
1593 {
1594  Vector<T,DIM> result;
1595  for( Size i = 0; i != DIM; ++i)
1596  result[i] = tan( v[i]);
1597  return result;
1598 }
1599 
1600 
1601 //------ Geometric Vector Algorithms ------------------------------------------
1602 
1604 template <typename T>
1605 inline T cross(
1606  const Vector<T,2>& lhs,
1607  const Vector<T,2>& rhs)
1608 {
1609  return lhs.x * rhs.y - lhs.y * rhs.x;
1610 }
1611 
1613 template <typename T>
1615  const Vector<T,3>& lhs,
1616  const Vector<T,3>& rhs)
1617 {
1618  return Vector<T,3>( lhs.y * rhs.z - lhs.z * rhs.y,
1619  lhs.z * rhs.x - lhs.x * rhs.z,
1620  lhs.x * rhs.y - lhs.y * rhs.x);
1621 }
1622 
1628 template <typename T>
1629 inline void make_basis(
1630  const Vector<T,3>& n,
1631  Vector<T,3>* u,
1632  Vector<T,3>* v)
1633 {
1634 #ifdef mi_base_assert_enabled
1635  const T eps = 1e-6f; // smallest resolvable factor
1636 #endif
1637 
1638  mi_math_assert_msg( u != 0, "precondition");
1639  mi_math_assert_msg( v != 0, "precondition");
1640  // Sanity check: the normal vector must be unit length.
1641  mi_math_assert_msg( abs( length(n) - 1.0f) < eps, "precondition");
1642 
1643  // Compute u.
1644  if( abs(n.x) < abs(n.y)) {
1645  // u = cross(x, n), x = (1, 0, 0)
1646  u->x = T(0);
1647  u->y = -n.z;
1648  u->z = n.y;
1649  } else {
1650  // u = cross(y, n), y = (0, 1, 0)
1651  u->x = n.z;
1652  u->y = T(0);
1653  u->z = -n.x;
1654  }
1655  u->normalize();
1656 
1657  // Compute v. Since *u and n are orthogonal and unit-length,
1658  // there is no need to normalize *v.
1659  *v = cross( *u, n);
1660 
1661  // Sanity check: make sure (u, n, v) is an orthogonal basis.
1662  mi_math_assert_msg( abs( dot( *u, n)) < eps, "postcondition");
1663  mi_math_assert_msg( abs( dot( *u, *v)) < eps, "postcondition");
1664  mi_math_assert_msg( abs( dot( n, *v)) < eps, "postcondition");
1665  // Sanity check: make sure u and v are unit length.
1666  mi_math_assert_msg( abs( length( *u) - T(1)) < eps, "postcondition");
1667  mi_math_assert_msg( abs( length( *v) - T(1)) < eps, "postcondition");
1668 }
1669 
1676 template <typename T>
1677 inline void make_basis(
1678  const Vector<T,3>& n,
1679  const Vector<T,3>& u,
1680  const Vector<T,3>& v,
1681  Vector<T,3>* t,
1682  Vector<T,3>* b)
1683 {
1684  const T eps = 1e-6f; // smallest resolvable factor
1685  (void)eps;
1686 
1687  mi_math_assert_msg( t != 0, "precondition");
1688  mi_math_assert_msg( b != 0, "precondition");
1689  // Sanity check: the normal vector must be unit length.
1690  mi_math_assert_msg( abs( length( n) - 1.0f) < eps, "precondition");
1691  // Sanity check: the other vector lengths should be finite and non-zero
1692  mi_math_assert_msg( length( u) > 0., "precondition");
1693  mi_math_assert_msg( length( v) > 0., "precondition");
1694  mi_math_assert_msg( isfinite( length( u)), "precondition");
1695  mi_math_assert_msg( isfinite( length( v)), "precondition");
1696 
1697  // Compute b
1698  *b = cross(u,n);
1699  b->normalize();
1700 
1701  // Compute t. Since *b and n are orthogonal and unit-length,
1702  // there is no need to normalize *t.
1703  *t = cross(n,*b);
1704 
1705  // Check that b has the same orientation of v
1706  if( dot( *b,v) < T(0))
1707  *b = -*b;
1708 
1709  // Sanity check: make sure *u and t have the same orientation.
1710  mi_math_assert_msg( dot( u, *t) > T(0), "postcondition");
1711  // Sanity check: make sure (t, n, b) is an orthogonal basis.
1712  // We use a scaled epsilon in order to avoid false positives.
1713  mi_math_assert_msg( abs( dot( *t, n)) < 20*eps, "postcondition");
1714  mi_math_assert_msg( abs( dot( *t, *b)) < 20*eps, "postcondition");
1715  mi_math_assert_msg( abs( dot( n, *b)) < 20*eps, "postcondition");
1716  // Sanity check: make sure t and b are unit length.
1717  mi_math_assert_msg( abs( length( *t) - T(1)) < eps, "postcondition");
1718  mi_math_assert_msg( abs( length( *b) - T(1)) < eps, "postcondition");
1719 }
1720 
1726 template <typename T2, Size DIM2, typename T1, Size DIM1>
1728  const Vector<T1, DIM1>& v,
1729  const T2& fill = T2(0))
1730 {
1731  const Size dim_min = base::min MI_PREVENT_MACRO_EXPAND ( DIM1, DIM2 );
1732  Vector<T2, DIM2> result;
1733  for( Size i = 0; i < dim_min; ++i)
1734  result[i] = T2(v[i]);
1735  for( Size i = dim_min; i < DIM2; ++i)
1736  result[i] = fill;
1737  return result;
1738 }
1739  // end group mi_math_vector
1741 
1742 } // namespace math
1743 
1744 } // namespace mi
1745 
1746 #endif // MI_MATH_VECTOR_H