NVIDIA Iray: Math API Home  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 1986, 2016 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 private:
260  Vector_proxy_& operator=( const Vector_proxy_& o);
261 };
262 
263 
264 
301 template < class T, Size DIM>
302 class Vector : public Vector_struct<T, DIM>
303 {
304 public:
307 
308  typedef T value_type;
309  typedef Size size_type;
311  typedef T * pointer;
312  typedef const T * const_pointer;
313  typedef T & reference;
314  typedef const T & const_reference;
315 
316  static const Size DIMENSION = DIM;
317  static const Size SIZE = DIM;
318 
320  static inline Size size() { return SIZE; }
321 
323  static inline Size max_size() { return SIZE; }
324 
326  inline T* begin() { return mi::math::vector_base_ptr( *this); }
327 
329  inline const T* begin() const { return mi::math::vector_base_ptr( *this); }
330 
334  inline T* end() { return begin() + DIM; }
335 
339  inline const T* end() const { return begin() + DIM; }
340 
342  inline Vector()
343  {
344 #if defined(DEBUG) || (defined(_MSC_VER) && _MSC_VER <= 1310)
345  // In debug mode, default-constructed vectors are initialized with signaling NaNs or, if not
346  // applicable, with a maximum value to increase the chances of diagnosing incorrect use of
347  // an uninitialized vector.
348  //
349  // When compiling with Visual C++ 7.1 or earlier, this code is enabled in all variants to
350  // work around a very obscure compiler bug that causes the compiler to crash.
351  typedef mi::base::numeric_traits<T> Traits;
352  T v = (Traits::has_signaling_NaN) ? Traits::signaling_NaN()
353  : Traits::max MI_PREVENT_MACRO_EXPAND ();
354  for( Size i(0u); i < DIM; ++i)
355  (*this)[i] = v;
356 #endif
357  }
358 
360  inline Vector( const Vector_struct<T,DIM>& vec )
361  {
362  for( Size i(0u); i < DIM; ++i)
363  (*this)[i] = mi::math::vector_base_ptr(vec)[i];
364  }
365 
367  inline explicit Vector(T v)
368  {
369  for( Size i(0u); i < DIM; ++i)
370  (*this)[i] = v;
371  }
372 
386  template <typename Iterator>
387  inline Vector(From_iterator_tag, Iterator p)
388  {
389  for( Size i(0u); i < DIM; ++i, ++p)
390  (*this)[i] = *p;
391  }
392 
404  template <typename T2>
405  inline explicit Vector( T2 const (& array)[DIM])
406  {
407  for( Size i(0u); i < DIM; ++i)
408  (*this)[i] = array[i];
409  }
410 
413  template <typename T2>
414  inline explicit Vector( const Vector<T2,DIM>& other)
415  {
416  for( Size i(0u); i < DIM; ++i)
417  (*this)[i] = T(other[i]);
418  }
419 
424  inline Vector(T v1, T v2)
425  {
426  mi_static_assert(DIM == 2);
427  begin()[0] = v1;
428  begin()[1] = v2;
429  }
430 
435  inline Vector(T v1, T v2, T v3)
436  {
437  mi_static_assert(DIM == 3);
438  begin()[0] = v1;
439  begin()[1] = v2;
440  begin()[2] = v3;
441  }
442 
447  inline Vector(T v1, const Vector<T,2>& v2)
448  {
449  mi_static_assert(DIM == 3);
450  begin()[0] = v1;
451  begin()[1] = v2.x;
452  begin()[2] = v2.y;
453  }
454 
459  inline Vector(const Vector<T,2>& v1, T v2)
460  {
461  mi_static_assert(DIM == 3);
462  begin()[0] = v1.x;
463  begin()[1] = v1.y;
464  begin()[2] = v2;
465  }
466 
471  inline Vector(T v1, T v2, T v3, T v4)
472  {
473  mi_static_assert(DIM == 4);
474  begin()[0] = v1;
475  begin()[1] = v2;
476  begin()[2] = v3;
477  begin()[3] = v4;
478  }
479 
484  inline Vector(T v1, T v2, const Vector<T,2>& v3)
485  {
486  mi_static_assert(DIM == 4);
487  begin()[0] = v1;
488  begin()[1] = v2;
489  begin()[2] = v3.x;
490  begin()[3] = v3.y;
491  }
492 
493 
498  inline Vector(T v1, const Vector<T,2>& v2, T v3)
499  {
500  mi_static_assert(DIM == 4);
501  begin()[0] = v1;
502  begin()[1] = v2.x;
503  begin()[2] = v2.y;
504  begin()[3] = v3;
505  }
506 
511  inline Vector(const Vector<T,2>& v1, T v2, T v3)
512  {
513  mi_static_assert(DIM == 4);
514  begin()[0] = v1.x;
515  begin()[1] = v1.y;
516  begin()[2] = v2;
517  begin()[3] = v3;
518  }
519 
524  inline Vector(const Vector<T,2>& v1, const Vector<T,2>& v2)
525  {
526  mi_static_assert(DIM == 4);
527  begin()[0] = v1.x;
528  begin()[1] = v1.y;
529  begin()[2] = v2.x;
530  begin()[3] = v2.y;
531  }
532 
537  inline Vector(T v1, const Vector<T,3>& v2)
538  {
539  mi_static_assert(DIM == 4);
540  begin()[0] = v1;
541  begin()[1] = v2.x;
542  begin()[2] = v2.y;
543  begin()[3] = v2.z;
544  }
545 
550  inline Vector(const Vector<T,3>& v1, T v2)
551  {
552  mi_static_assert(DIM == 4);
553  begin()[0] = v1.x;
554  begin()[1] = v1.y;
555  begin()[2] = v1.z;
556  begin()[3] = v2;
557  }
558 
563  inline explicit Vector( const Color_struct& color)
564  {
565  mi_static_assert(DIM == 4);
566  this->x = color.r;
567  this->y = color.g;
568  this->z = color.b;
569  this->w = color.a;
570  }
571 
573  inline Vector& operator= ( const Vector& other)
574  {
575  for( Size i(0u); i < DIM; ++i)
576  (*this)[i] = other[i];
577  return *this;
578  }
579 
581  inline Vector& operator= ( T s)
582  {
583  for( Size i(0u); i < DIM; ++i)
584  (*this)[i] = s;
585  return *this;
586  }
591  inline Vector& operator= ( const Color_struct& color)
592  {
593  mi_static_assert(DIM == 4);
594  this->x = color.r;
595  this->y = color.g;
596  this->z = color.b;
597  this->w = color.a;
598  return *this;
599  }
600 
604  inline T& operator[] (Size i)
605  {
606  mi_math_assert_msg(i < DIM, "precondition");
607  return begin()[i];
608  }
609 
613  inline const T& operator[] (Size i) const
614  {
615  mi_math_assert_msg(i < DIM, "precondition");
616  return begin()[i];
617  }
618 
622  inline const T& get(Size i) const
623  {
624  mi_math_assert_msg(i < DIM, "precondition");
625  return begin()[i];
626  }
627 
631  inline void set(Size i, T value)
632  {
633  mi_math_assert_msg(i < DIM, "precondition");
634  begin()[i] = value;
635  }
636 
637 
638 
645  inline bool normalize()
646  {
647  const T rec_length = T(1) / length( *this);
648  const bool result = isfinite( rec_length);
649  if( result)
650  (*this) *= rec_length;
651  return result;
652  }
653 
654 
655  //------ Free comparison operators ==, !=, <, <=, >, >= for vectors --------
656  // Using a proxy class to make comparison operators a lesser match when it comes
657  // to an overload resolution set with the MetaSL definitions of these operators.
658 
660  inline bool operator==( Vector_proxy_<T,DIM> rhs) const
661  {
662  return is_equal( *this, rhs.vec);
663  }
664 
666  inline bool operator!=( Vector_proxy_<T,DIM> rhs) const
667  {
668  return is_not_equal( *this, rhs.vec);
669  }
670 
674  inline bool operator<( Vector_proxy_<T,DIM> rhs) const
675  {
676  return lexicographically_less( *this, rhs.vec);
677  }
678 
682  inline bool operator<=( Vector_proxy_<T,DIM> rhs) const
683  {
684  return lexicographically_less_or_equal( *this, rhs.vec);
685  }
686 
690  inline bool operator>( Vector_proxy_<T,DIM> rhs) const
691  {
692  return lexicographically_greater( *this, rhs.vec);
693  }
694 
698  inline bool operator>=( Vector_proxy_<T,DIM> rhs) const
699  {
700  return lexicographically_greater_or_equal( *this, rhs.vec);
701  }
702 };
703 
704 
705 //------ Free operators +=, -=, *=, /=, +, -, *, and / for vectors -------------
706 
708 template <typename T, Size DIM>
710  Vector<T,DIM>& lhs,
711  const Vector<T,DIM>& rhs)
712 {
713  for( Size i(0u); i < DIM; ++i)
714  lhs[i] += rhs[i];
715  return lhs;
716 }
717 
719 template <typename T, Size DIM>
721  Vector<T,DIM>& lhs,
722  const Vector<T,DIM>& rhs)
723 {
724  for( Size i(0u); i < DIM; ++i)
725  lhs[i] -= rhs[i];
726  return lhs;
727 }
728 
730 template <typename T, Size DIM>
732  Vector<T,DIM>& lhs,
733  const Vector<T,DIM>& rhs)
734 {
735  for( Size i(0u); i < DIM; ++i)
736  lhs[i] *= rhs[i];
737  return lhs;
738 }
739 
742 template <typename T, Size DIM>
744  Vector<T,DIM>& lhs,
745  const Vector<T,DIM>& rhs)
746 {
747  for( Size i(0u); i < DIM; ++i)
748  lhs[i] %= rhs[i];
749  return lhs;
750 }
751 
753 template <typename T, typename U, Size DIM>
755  Vector<T,DIM>& lhs,
756  const Vector<U,DIM>& rhs)
757 {
758  for( Size i(0u); i < DIM; ++i)
759  lhs[i] = T(lhs[i] / rhs[i]);
760  return lhs;
761 }
762 
764 template <typename T, Size DIM>
766  const Vector<T,DIM>& lhs,
767  const Vector<T,DIM>& rhs)
768 {
769  Vector<T,DIM> tmp( lhs);
770  return tmp += rhs;
771 }
772 
774 template <typename T, Size DIM>
776  const Vector<T,DIM>& lhs,
777  const Vector<T,DIM>& rhs)
778 {
779  Vector<T,DIM> tmp( lhs);
780  return tmp -= rhs;
781 }
782 
784 template <typename T, Size DIM>
786  const Vector<T,DIM>& lhs,
787  const Vector<T,DIM>& rhs)
788 {
789  Vector<T,DIM> tmp( lhs);
790  return tmp *= rhs;
791 }
792 
795 template <typename T, Size DIM>
797  const Vector<T,DIM>& lhs,
798  const Vector<T,DIM>& rhs)
799 {
800  Vector<T,DIM> tmp( lhs);
801  return tmp %= rhs;
802 }
803 
805 template <typename T, typename U, Size DIM>
807  const Vector<T,DIM>& lhs,
808  const Vector<U,DIM>& rhs)
809 {
810  Vector<T,DIM> tmp(lhs);
811  return tmp /= rhs;
812 }
813 
815 template <typename T, Size DIM>
817 {
818  Vector<T,DIM> tmp;
819  for( Size i(0u); i < DIM; ++i)
820  tmp[i] = -v[i];
821  return tmp;
822 }
823 
824 
825 //------ Free operator *=, /=, *, and / definitions for scalars ---------------
826 
829 template <typename T, typename TT, Size DIM>
831  Vector<T,DIM>& v,
832  TT s)
833 {
834  for( Size i(0u); i < DIM; ++i)
835  v[i] = T(v[i] * s);
836  return v;
837 }
838 
842 template <typename T, typename TT, Size DIM>
844  Vector<T,DIM>& v,
845  TT s)
846 {
847  for( Size i(0u); i < DIM; ++i)
848  v[i] = T(v[i] % s);
849  return v;
850 }
851 
853 template <typename T, typename TT, Size DIM>
855  Vector<T,DIM>& v,
856  TT s)
857 {
858  for( Size i(0u); i < DIM; ++i)
859  v[i] = T(v[i] / s);
860  return v;
861 }
862 
864 template <typename T, typename TT, Size DIM>
866  const Vector<T,DIM>& v,
867  TT s)
868 {
869  Vector<T,DIM> tmp( v);
870  return tmp *= s;
871 }
872 
874 template <typename T, typename TT, Size DIM>
876  TT s,
877  const Vector<T,DIM>& v)
878 {
879  Vector<T,DIM> tmp(v);
880  return tmp *= s;
881 }
882 
886 template <typename T, typename TT, Size DIM>
888  const Vector<T,DIM>& v,
889  TT s)
890 {
891  Vector<T,DIM> tmp(v);
892  return tmp %= s;
893 }
894 
896 template <typename T, typename TT, Size DIM>
898  const Vector<T,DIM>& v,
899  TT s)
900 {
901  Vector<T,DIM> tmp( v);
902  return tmp /= s;
903 }
904 
905 
906 //------ Free operator ++, -- for vectors -------------------------------------
907 
909 template <typename T, Size DIM>
911 {
913  return vec;
914 }
915 
917 template <typename T, Size DIM>
919 {
921  return vec;
922 }
923 
924 
925 //------ Free operators !, &&, ||, ^ for bool vectors and bool scalars ---------
926 
928 template <Size DIM>
930  const Vector<bool,DIM>& lhs,
931  const Vector<bool,DIM>& rhs)
932 {
933  Vector<bool,DIM> result;
934  general::transform( lhs, rhs, result, functor::Operator_and_and());
935  return result;
936 }
937 
939 template <Size DIM>
941  bool lhs,
942  const Vector<bool,DIM>& rhs)
943 {
944  Vector<bool,DIM> result;
946  return result;
947 }
948 
950 template <Size DIM>
952  const Vector<bool,DIM>& lhs,
953  bool rhs)
954 {
955  Vector<bool,DIM> result;
957  return result;
958 }
959 
961 template <Size DIM>
963  const Vector<bool,DIM>& lhs,
964  const Vector<bool,DIM>& rhs)
965 {
966  Vector<bool,DIM> result;
967  general::transform(lhs, rhs, result, functor::Operator_or_or());
968  return result;
969 }
970 
972 template <Size DIM>
974  bool lhs,
975  const Vector<bool,DIM>& rhs)
976 {
977  Vector<bool,DIM> result;
979  return result;
980 }
981 
983 template <Size DIM>
985  const Vector<bool,DIM>& lhs,
986  bool rhs)
987 {
988  Vector<bool,DIM> result;
990  return result;
991 }
992 
994 template <Size DIM>
996  const Vector<bool,DIM>& lhs,
997  const Vector<bool,DIM>& rhs)
998 {
999  Vector<bool,DIM> result;
1000  general::transform( lhs, rhs, result, functor::Operator_xor());
1001  return result;
1002 }
1003 
1005 template <Size DIM>
1007  bool lhs,
1008  const Vector<bool,DIM>& rhs)
1009 {
1010  Vector<bool,DIM> result;
1012  return result;
1013 }
1014 
1016 template <Size DIM>
1018  const Vector<bool,DIM>& lhs,
1019  bool rhs)
1020 {
1021  Vector<bool,DIM> result;
1023  return result;
1024 }
1025 
1027 template <Size DIM>
1029  const Vector<bool,DIM>& vec)
1030 {
1031  Vector<bool,DIM> result;
1032  general::transform( vec, result, functor::Operator_not());
1033  return result;
1034 }
1035 
1036 
1037 //------ Elementwise comparison operators returning a bool vector. ------------
1038 
1040 template <typename T, Size DIM>
1042  const Vector<T,DIM>& lhs,
1043  const Vector<T,DIM>& rhs)
1044 {
1045  Vector<bool,DIM> result;
1047  return result;
1048 }
1049 
1051 template <typename T, Size DIM>
1053  const Vector<T,DIM>& lhs,
1054  const Vector<T,DIM>& rhs)
1055 {
1056  Vector<bool,DIM> result;
1057  general::transform( lhs, rhs, result,functor::Operator_not_equal());
1058  return result;
1059 }
1060 
1062 template <typename T, Size DIM>
1064  const Vector<T,DIM>& lhs,
1065  const Vector<T,DIM>& rhs)
1066 {
1067  Vector<bool,DIM> result;
1068  general::transform( lhs, rhs, result,functor::Operator_less());
1069  return result;
1070 }
1071 
1073 template <typename T, Size DIM>
1075  const Vector<T,DIM>& lhs,
1076  const Vector<T,DIM>& rhs)
1077 {
1078  Vector<bool,DIM> result;
1079  general::transform( lhs, rhs, result,functor::Operator_less_equal());
1080  return result;
1081 }
1082 
1084 template <typename T, Size DIM>
1086  const Vector<T,DIM>& lhs,
1087  const Vector<T,DIM>& rhs)
1088 {
1089  Vector<bool,DIM> result;
1090  general::transform( lhs, rhs, result,functor::Operator_greater());
1091  return result;
1092 }
1093 
1095 template <typename T, Size DIM>
1097  const Vector<T,DIM>& lhs,
1098  const Vector<T,DIM>& rhs)
1099 {
1100  Vector<bool,DIM> result;
1102  return result;
1103 }
1104 
1105 
1106 //------ Function Overloads for Vector Algorithms -----------------------------
1107 
1109 template <typename T, Size DIM>
1111 {
1112  Vector<T,DIM> result;
1113  for( Size i = 0; i != DIM; ++i)
1114  result[i] = abs( v[i]);
1115  return result;
1116 }
1117 
1119 template <typename T, Size DIM>
1121 {
1122  Vector<T,DIM> result;
1123  for( Size i = 0; i != DIM; ++i)
1124  result[i] = acos( v[i]);
1125  return result;
1126 }
1127 
1129 template <typename T, Size DIM>
1130 inline bool all( const Vector<T,DIM>& v)
1131 {
1132  for( Size i = 0; i != DIM; ++i)
1133  if( !all(v[i]))
1134  return false;
1135  return true;
1136 }
1137 
1139 template <typename T, Size DIM>
1140 inline bool any( const Vector<T,DIM>& v)
1141 {
1142  for( Size i = 0; i != DIM; ++i)
1143  if( any(v[i]))
1144  return true;
1145  return false;
1146 }
1147 
1149 template <typename T, Size DIM>
1151 {
1152  Vector<T,DIM> result;
1153  for( Size i = 0; i != DIM; ++i)
1154  result[i] = asin( v[i]);
1155  return result;
1156 }
1157 
1159 template <typename T, Size DIM>
1161 {
1162  Vector<T,DIM> result;
1163  for( Size i = 0; i != DIM; ++i)
1164  result[i] = atan( v[i]);
1165  return result;
1166 }
1167 
1171 template <typename T, Size DIM>
1172 inline Vector<T,DIM> atan2( const Vector<T,DIM>& v, const Vector<T,DIM>& w)
1173 {
1174  Vector<T,DIM> result;
1175  for( Size i = 0; i != DIM; ++i)
1176  result[i] = atan2( v[i], w[i]);
1177  return result;
1178 }
1179 
1182 template <typename T, Size DIM>
1184 {
1185  Vector<T,DIM> result;
1186  for( Size i = 0; i != DIM; ++i)
1187  result[i] = ceil( v[i]);
1188  return result;
1189 }
1190 
1192 template <typename T, Size DIM>
1194  const Vector<T,DIM>& v,
1195  const Vector<T,DIM>& low,
1196  const Vector<T,DIM>& high)
1197 {
1198  Vector<T,DIM> result;
1199  for( Size i = 0u; i < DIM; ++i)
1200  result[i] = clamp( v[i], low[i], high[i]);
1201  return result;
1202 }
1203 
1205 template <typename T, Size DIM>
1207  const Vector<T,DIM>& v,
1208  const Vector<T,DIM>& low,
1209  T high)
1210 {
1211  Vector<T,DIM> result;
1212  for( Size i = 0u; i < DIM; ++i)
1213  result[i] = clamp( v[i], low[i], high);
1214  return result;
1215 }
1216 
1218 template <typename T, Size DIM>
1220  const Vector<T,DIM>& v,
1221  T low,
1222  const Vector<T,DIM>& high)
1223 {
1224  Vector<T,DIM> result;
1225  for( Size i = 0u; i < DIM; ++i)
1226  result[i] = clamp( v[i], low, high[i]);
1227  return result;
1228 }
1229 
1231 template <typename T, Size DIM>
1233  const Vector<T,DIM>& v,
1234  T low,
1235  T high)
1236 {
1237  Vector<T,DIM> result;
1238  for( Size i = 0u; i < DIM; ++i)
1239  result[i] = clamp( v[i], low, high);
1240  return result;
1241 }
1242 
1244 template <typename T, Size DIM>
1246 {
1247  Vector<T,DIM> result;
1248  for( Size i = 0; i != DIM; ++i)
1249  result[i] = cos( v[i]);
1250  return result;
1251 }
1252 
1254 template <typename T, Size DIM>
1256 {
1257  Vector<T,DIM> result;
1258  for( Size i = 0; i != DIM; ++i)
1259  result[i] = degrees( v[i]);
1260  return result;
1261 }
1262 
1264 template <typename T, Size DIM>
1266  const Vector<T,DIM>& lhs,
1267  const Vector<T,DIM>& rhs)
1268 {
1269  Vector<T,DIM> r;
1270  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1271  r[i] = base::max MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1272  return r;
1273 }
1274 
1276 template <typename T, Size DIM>
1278  const Vector<T,DIM>& lhs,
1279  const Vector<T,DIM>& rhs)
1280 {
1281  Vector<T,DIM> r;
1282  for( Size i(0u); i < Vector<T,DIM>::DIMENSION; ++i)
1283  r[i] = base::min MI_PREVENT_MACRO_EXPAND ( lhs[i], rhs[i] );
1284  return r;
1285 }
1286 
1288 template <typename T, Size DIM>
1290 {
1291  Vector<T,DIM> result;
1292  for( Size i = 0; i != DIM; ++i)
1293  result[i] = exp( v[i]);
1294  return result;
1295 }
1296 
1298 template <typename T, Size DIM>
1300 {
1301  Vector<T,DIM> result;
1302  for( Size i = 0; i != DIM; ++i)
1303  result[i] = exp2( v[i]);
1304  return result;
1305 }
1306 
1309 template <typename T, Size DIM>
1311 {
1312  Vector<T,DIM> result;
1313  for( Size i = 0; i != DIM; ++i)
1314  result[i] = floor( v[i]);
1315  return result;
1316 }
1317 
1321 template <typename T, Size DIM>
1322 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1323 {
1324  Vector<T,DIM> result;
1325  for( Size i = 0; i != DIM; ++i)
1326  result[i] = fmod( a[i], b[i]);
1327  return result;
1328 }
1329 
1333 template <typename T, Size DIM>
1334 inline Vector<T,DIM> fmod( const Vector<T,DIM>& a, T b)
1335 {
1336  Vector<T,DIM> result;
1337  for( Size i = 0; i != DIM; ++i)
1338  result[i] = fmod( a[i], b);
1339  return result;
1340 }
1341 
1343 template <typename T, Size DIM>
1345 {
1346  Vector<T,DIM> result;
1347  for( Size i = 0; i != DIM; ++i)
1348  result[i] = frac( v[i]);
1349  return result;
1350 }
1351 
1353 template <typename T, Size DIM>
1354 inline bool is_approx_equal(
1355  const Vector<T,DIM>& left,
1356  const Vector<T,DIM>& right,
1357  T e)
1358 {
1359  for( Size i = 0u; i < DIM; ++i)
1360  if( !is_approx_equal( left[i], right[i], e))
1361  return false;
1362  return true;
1363 }
1364 
1367 template <typename T, Size DIM>
1369  const Vector<T,DIM>& v1,
1370  const Vector<T,DIM>& v2,
1371  const Vector<T,DIM>& t)
1372 {
1373  Vector<T,DIM> result;
1374  for( Size i = 0; i != DIM; ++i)
1375  result[i] = v1[i] * (T(1)-t[i]) + v2[i] * t[i];
1376  return result;
1377 }
1378 
1381 template <typename T, Size DIM>
1383  const Vector<T,DIM>& v1,
1384  const Vector<T,DIM>& v2,
1385  T t)
1386 {
1387  // equivalent to: return v1 * (T(1)-t) + v2 * t;
1388  Vector<T,DIM> result;
1389  T t2 = T(1) - t;
1390  for( Size i = 0; i != DIM; ++i)
1391  result[i] = v1[i] * t2 + v2[i] * t;
1392  return result;
1393 }
1394 
1396 template <typename T, Size DIM>
1398 {
1399  Vector<T,DIM> result;
1400  for( Size i = 0; i != DIM; ++i)
1401  result[i] = log( v[i]);
1402  return result;
1403 }
1404 
1406 template <typename T, Size DIM>
1408 {
1409  Vector<T,DIM> result;
1410  for( Size i = 0; i != DIM; ++i)
1411  result[i] = log2 MI_PREVENT_MACRO_EXPAND ( v[i]);
1412  return result;
1413 }
1414 
1416 template <typename T, Size DIM>
1418 {
1419  Vector<T,DIM> result;
1420  for( Size i = 0; i != DIM; ++i)
1421  result[i] = log10( v[i]);
1422  return result;
1423 }
1424 
1429 template <typename T, Size DIM>
1431 {
1432  Vector<T,DIM> result;
1433  for( Size j = 0; j != DIM; ++j)
1434  result[j] = modf( v[j], i[j]);
1435  return result;
1436 }
1437 
1439 template <typename T, Size DIM>
1440 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, const Vector<T,DIM>& b)
1441 {
1442  Vector<T,DIM> result;
1443  for( Size i = 0; i != DIM; ++i)
1444  result[i] = pow( a[i], b[i]);
1445  return result;
1446 }
1447 
1449 template <typename T, Size DIM>
1450 inline Vector<T,DIM> pow( const Vector<T,DIM>& a, T b)
1451 {
1452  Vector<T,DIM> result;
1453  for( Size i = 0; i != DIM; ++i)
1454  result[i] = pow( a[i], b);
1455  return result;
1456 }
1457 
1459 template <typename T, Size DIM>
1461 {
1462  Vector<T,DIM> result;
1463  for( Size i = 0; i != DIM; ++i)
1464  result[i] = radians( v[i]);
1465  return result;
1466 }
1467 
1469 template <typename T, Size DIM>
1471 {
1472  Vector<T,DIM> result;
1473  for( Size i = 0; i != DIM; ++i)
1474  result[i] = round( v[i]);
1475  return result;
1476 }
1477 
1479 template <typename T, Size DIM>
1481 {
1482  Vector<T,DIM> result;
1483  for( Size i = 0; i != DIM; ++i)
1484  result[i] = rsqrt( v[i]);
1485  return result;
1486 }
1487 
1489 template <typename T, Size DIM>
1491 {
1492  Vector<T,DIM> result;
1493  for( Size i = 0; i != DIM; ++i)
1494  result[i] = saturate( v[i]);
1495  return result;
1496 }
1497 
1499 template <typename T, Size DIM>
1501 {
1502  Vector<T,DIM> result;
1503  for( Size i = 0; i != DIM; ++i)
1504  result[i] = sign( v[i]);
1505  return result;
1506 }
1507 
1509 template <typename T, Size DIM>
1511 {
1512  Vector<T,DIM> result;
1513  for( Size i = 0; i != DIM; ++i)
1514  result[i] = sin( v[i]);
1515  return result;
1516 }
1517 
1521 template <typename T, Size DIM>
1522 inline void sincos( const Vector<T,DIM>& a, Vector<T,DIM>& s, Vector<T,DIM>& c)
1523 {
1524  for( Size i = 0; i != DIM; ++i)
1525  sincos( a[i], s[i], c[i]);
1526 }
1527 
1533 template <typename T, Size DIM>
1535  const Vector<T,DIM>& a,
1536  const Vector<T,DIM>& b,
1537  const Vector<T,DIM>& v)
1538 {
1539  Vector<T,DIM> result;
1540  for( Size i = 0; i != DIM; ++i)
1541  result[i] = smoothstep( a[i], b[i], v[i]);
1542  return result;
1543 }
1544 
1550 template <typename T, Size DIM>
1552  const Vector<T,DIM>& a,
1553  const Vector<T,DIM>& b,
1554  T x)
1555 {
1556  Vector<T,DIM> result;
1557  for( Size i = 0; i != DIM; ++i)
1558  result[i] = smoothstep( a[i], b[i], x);
1559  return result;
1560 }
1561 
1563 template <typename T, Size DIM>
1565 {
1566  Vector<T,DIM> result;
1567  for( Size i = 0; i != DIM; ++i)
1568  result[i] = sqrt( v[i]);
1569  return result;
1570 }
1571 
1573 template <typename T, Size DIM>
1574 inline Vector<T,DIM> step( const Vector<T,DIM>& a, const Vector<T,DIM>& v)
1575 {
1576  Vector<T,DIM> result;
1577  for( Size i = 0; i != DIM; ++i)
1578  result[i] = step( a[i], v[i]);
1579  return result;
1580 }
1581 
1583 template <typename T, Size DIM>
1585 {
1586  Vector<T,DIM> result;
1587  for( Size i = 0; i != DIM; ++i)
1588  result[i] = tan( v[i]);
1589  return result;
1590 }
1591 
1592 
1593 //------ Geometric Vector Algorithms ------------------------------------------
1594 
1596 template <typename T>
1597 inline T cross(
1598  const Vector<T,2>& lhs,
1599  const Vector<T,2>& rhs)
1600 {
1601  return lhs.x * rhs.y - lhs.y * rhs.x;
1602 }
1603 
1605 template <typename T>
1607  const Vector<T,3>& lhs,
1608  const Vector<T,3>& rhs)
1609 {
1610  return Vector<T,3>( lhs.y * rhs.z - lhs.z * rhs.y,
1611  lhs.z * rhs.x - lhs.x * rhs.z,
1612  lhs.x * rhs.y - lhs.y * rhs.x);
1613 }
1614 
1620 template <typename T>
1621 inline void make_basis(
1622  const Vector<T,3>& n,
1623  Vector<T,3>* u,
1624  Vector<T,3>* v)
1625 {
1626 #ifdef mi_base_assert_enabled
1627  const T eps = 1e-6f; // smallest resolvable factor
1628 #endif
1629 
1630  mi_math_assert_msg( u != 0, "precondition");
1631  mi_math_assert_msg( v != 0, "precondition");
1632  // Sanity check: the normal vector must be unit length.
1633  mi_math_assert_msg( abs( length(n) - 1.0f) < eps, "precondition");
1634 
1635  // Compute u.
1636  if( abs(n.x) < abs(n.y)) {
1637  // u = cross(x, n), x = (1, 0, 0)
1638  u->x = T(0);
1639  u->y = -n.z;
1640  u->z = n.y;
1641  } else {
1642  // u = cross(y, n), y = (0, 1, 0)
1643  u->x = n.z;
1644  u->y = T(0);
1645  u->z = -n.x;
1646  }
1647  u->normalize();
1648 
1649  // Compute v. Since *u and n are orthogonal and unit-length,
1650  // there is no need to normalize *v.
1651  *v = cross( *u, n);
1652 
1653  // Sanity check: make sure (u, n, v) is an orthogonal basis.
1654  mi_math_assert_msg( abs( dot( *u, n)) < eps, "postcondition");
1655  mi_math_assert_msg( abs( dot( *u, *v)) < eps, "postcondition");
1656  mi_math_assert_msg( abs( dot( n, *v)) < eps, "postcondition");
1657  // Sanity check: make sure u and v are unit length.
1658  mi_math_assert_msg( abs( length( *u) - T(1)) < eps, "postcondition");
1659  mi_math_assert_msg( abs( length( *v) - T(1)) < eps, "postcondition");
1660 }
1661 
1668 template <typename T>
1669 inline void make_basis(
1670  const Vector<T,3>& n,
1671  const Vector<T,3>& u,
1672  const Vector<T,3>& v,
1673  Vector<T,3>* t,
1674  Vector<T,3>* b)
1675 {
1676  const T eps = 1e-6f; // smallest resolvable factor
1677  (void)eps;
1678 
1679  mi_math_assert_msg( t != 0, "precondition");
1680  mi_math_assert_msg( b != 0, "precondition");
1681  // Sanity check: the normal vector must be unit length.
1682  mi_math_assert_msg( abs( length( n) - 1.0f) < eps, "precondition");
1683  // Sanity check: the other vector lengths should be finite and non-zero
1684  mi_math_assert_msg( length( u) > 0., "precondition");
1685  mi_math_assert_msg( length( v) > 0., "precondition");
1686  mi_math_assert_msg( isfinite( length( u)), "precondition");
1687  mi_math_assert_msg( isfinite( length( v)), "precondition");
1688 
1689  // Compute b
1690  *b = cross(u,n);
1691  b->normalize();
1692 
1693  // Compute t. Since *b and n are orthogonal and unit-length,
1694  // there is no need to normalize *t.
1695  *t = cross(n,*b);
1696 
1697  // Check that b has the same orientation of v
1698  if( dot( *b,v) < T(0))
1699  *b = -*b;
1700 
1701  // Sanity check: make sure *u and t have the same orientation.
1702  mi_math_assert_msg( dot( u, *t) > T(0), "postcondition");
1703  // Sanity check: make sure (t, n, b) is an orthogonal basis.
1704  // We use a scaled epsilon in order to avoid false positives.
1705  mi_math_assert_msg( abs( dot( *t, n)) < 20*eps, "postcondition");
1706  mi_math_assert_msg( abs( dot( *t, *b)) < 20*eps, "postcondition");
1707  mi_math_assert_msg( abs( dot( n, *b)) < 20*eps, "postcondition");
1708  // Sanity check: make sure t and b are unit length.
1709  mi_math_assert_msg( abs( length( *t) - T(1)) < eps, "postcondition");
1710  mi_math_assert_msg( abs( length( *b) - T(1)) < eps, "postcondition");
1711 }
1712 
1718 template <typename T2, Size DIM2, typename T1, Size DIM1>
1720  const Vector<T1, DIM1>& v,
1721  const T2& fill = T2(0))
1722 {
1723  const Size dim_min = base::min MI_PREVENT_MACRO_EXPAND ( DIM1, DIM2 );
1724  Vector<T2, DIM2> result;
1725  for( Size i = 0; i < dim_min; ++i)
1726  result[i] = T2(v[i]);
1727  for( Size i = dim_min; i < DIM2; ++i)
1728  result[i] = fill;
1729  return result;
1730 }
1731  // end group mi_math_vector
1733 
1734 } // namespace math
1735 
1736 } // namespace mi
1737 
1738 #endif // MI_MATH_VECTOR_H