Mathter
A configurable 3D math library for game developers.
VectorFunction.hpp
Go to the documentation of this file.
1 #pragma once
2 
3 #if _MSC_VER && defined(min)
4 #pragma push_macro("min")
5 #pragma push_macro("max")
6 #undef min
7 #undef max
8 #define MATHTER_MINMAX
9 #endif
10 
11 
12 #include "VectorImpl.hpp"
13 
14 namespace mathter {
15 
16 
20 template <class T, int Dim, bool Packed>
22  static constexpr T epsilon = T(1) / ConstexprExp10<T>(ConstexprAbs(std::numeric_limits<T>::min_exponent10) / 2);
23  T length = Length(v);
24  return length < epsilon;
25 }
26 
28 template <class T, int Dim, bool Packed>
30  return Dot(v, v);
31 }
32 
34 template <class T, int Dim, bool Packed>
36  return (T)sqrt((T)LengthSquared(v));
37 }
38 
40 template <class T, int Dim, bool Packed>
42  T maxElement = std::abs(v(0));
43  for (int i = 1; i < v.Dimension(); ++i) {
44  maxElement = std::max(maxElement, std::abs(v(i)));
45  }
46  if (maxElement == T(0)) {
47  return T(0);
48  }
49  auto scaled = v / maxElement;
50  return sqrt(Dot(scaled, scaled)) * maxElement;
51 }
52 
54 template <class T, class U, int Dim, bool Packed1, bool Packed2>
56  return (lhs - rhs).Length();
57 }
58 
60 template <class T, int Dim, bool Packed>
62  assert(!IsNullvector(v));
63  T l = Length(v);
64  return v / l;
65 }
66 
68 template <class T, int Dim, bool Packed>
70  T n = LengthSquared(v);
71  return T(0.9999) <= n && n <= T(1.0001);
72 }
73 
75 template <class T, int Dim, bool Packed>
77  Vector<T, Dim, Packed> vmod = v;
78  vmod(0) = std::abs(v(0)) > std::numeric_limits<T>::denorm_min() ? v(0) : std::numeric_limits<T>::denorm_min();
79  T l = LengthPrecise(vmod);
80  return vmod / l;
81 }
82 
85 template <class T, int Dim, bool Packed>
87  assert(IsNormalized(degenerate));
88  T length = LengthPrecise(v);
89  if (length == 0) {
90  return degenerate;
91  }
92  return v / length;
93 }
94 
96 template <class T, int Dim, bool Packed>
97 void Fill(Vector<T, Dim, Packed>& lhs, T all) {
98  if constexpr (!traits::HasSimd<Vector<T, Dim, Packed>>::value) {
99  for (auto& v : lhs) {
100  v = all;
101  }
102  }
103  else {
104  using SimdT = decltype(VectorData<T, Dim, Packed>::simd);
105  lhs.simd = SimdT::spread(all);
106  }
107 }
108 
110 template <class T, int Dim, bool Packed>
112  if constexpr (!traits::HasSimd<Vector<T, Dim, Packed>>::value) {
113  T sum = T(0);
114  for (int i = 0; i < Dim; ++i) {
115  sum += lhs.data[i] * rhs.data[i];
116  }
117  return sum;
118  }
119  else {
120  using SimdT = decltype(VectorData<T, Dim, Packed>::simd);
121  return SimdT::template dot<Dim>(lhs.simd, rhs.simd);
122  }
123 }
124 
129 template <class T, int Dim, bool Packed, class... Args>
130 auto Cross(const Vector<T, Dim, Packed>& head, Args&&... args) -> Vector<T, Dim, Packed>;
131 
132 
135 template <class T, int Dim, bool Packed>
136 auto Cross(const std::array<const Vector<T, Dim, Packed>*, Dim - 1>& args) -> Vector<T, Dim, Packed>;
137 
139 template <class T, bool Packed>
141  return Vector<T, 2, Packed>(-arg.y,
142  arg.x);
143 }
145 template <class T, bool Packed>
146 Vector<T, 2, Packed> Cross(const std::array<const Vector<T, 2, Packed>*, 1>& arg) {
147  return Cross(*(arg[0]));
148 }
149 
150 
152 template <class T, bool Packed>
154  return Vector<T, 3, Packed>(lhs.y * rhs.z - lhs.z * rhs.y,
155  lhs.z * rhs.x - lhs.x * rhs.z,
156  lhs.x * rhs.y - lhs.y * rhs.x);
157 }
159 template <class T, bool Packed>
160 Vector<T, 3, Packed> Cross(const std::array<const Vector<T, 3, Packed>*, 2>& args) {
161  return Cross(*(args[0]), *(args[1]));
162 }
163 
164 
166 template <class T, int Dim, bool Packed>
169  for (int i = 0; i < lhs.Dimension(); ++i) {
170  res[i] = std::min(lhs[i], rhs[i]);
171  }
172  return res;
173 }
175 template <class T, int Dim, bool Packed>
178  for (int i = 0; i < lhs.Dimension(); ++i) {
179  res[i] = std::max(lhs[i], rhs[i]);
180  }
181  return res;
182 }
183 
184 
185 } // namespace mathter
186 
187 
188 
189 // Generalized cross-product unfortunately needs matrix determinant.
190 #include "../Matrix.hpp"
191 
192 namespace mathter {
193 
194 template <class T, int Dim, bool Packed>
195 auto Cross(const std::array<const Vector<T, Dim, Packed>*, Dim - 1>& args) -> Vector<T, Dim, Packed> {
196  Vector<T, Dim, Packed> result;
197  Matrix<T, Dim - 1, Dim - 1, eMatrixOrder::FOLLOW_VECTOR, eMatrixLayout::ROW_MAJOR, false> detCalc;
198 
199  // Calculate elements of result on-by-one
200  int sign = 2 * (Dim % 2) - 1;
201  for (int base = 0; base < result.Dimension(); ++base, sign *= -1) {
202  // Fill up sub-matrix the determinant of which yields the coefficient of base-vector.
203  for (int j = 0; j < base; ++j) {
204  for (int i = 0; i < detCalc.RowCount(); ++i) {
205  detCalc(i, j) = (*(args[i]))[j];
206  }
207  }
208  for (int j = base + 1; j < result.Dimension(); ++j) {
209  for (int i = 0; i < detCalc.RowCount(); ++i) {
210  detCalc(i, j - 1) = (*(args[i]))[j];
211  }
212  }
213 
214  T coefficient = T(sign) * Determinant(detCalc);
215  result(base) = coefficient;
216  }
217 
218  return result;
219 }
220 
221 
222 template <class T, int Dim, bool Packed, class... Args>
223 auto Cross(const Vector<T, Dim, Packed>& head, Args&&... args) -> Vector<T, Dim, Packed> {
224  static_assert(1 + sizeof...(args) == Dim - 1, "Number of arguments must be (Dimension - 1).");
225 
226  std::array<const Vector<T, Dim, Packed>*, Dim - 1> vectors = { &head, &args... };
227  return Cross(vectors);
228 }
229 
230 } // namespace mathter
231 
232 
233 #if defined(MATHTER_MINMAX)
234 #pragma pop_macro("min")
235 #pragma pop_macro("max")
236 #endif
void Fill(Vector< T, Dim, Packed > &lhs, T all)
Sets all elements of the vector to the same value.
Definition: VectorFunction.hpp:97
Vector< T, Dim, Packed > Min(const Vector< T, Dim, Packed > &lhs, const Vector< T, Dim, Packed > &rhs)
Returns the element-wise minimum of arguments
Definition: VectorFunction.hpp:167
auto Distance(const Vector< T, Dim, Packed1 > &lhs, const Vector< U, Dim, Packed2 > &rhs)
Returns the euclidean distance between to vectors.
Definition: VectorFunction.hpp:55
bool IsNullvector(const Vector< T, Dim, Packed > &v)
Returns true if the vector&#39;s length is too small for precise calculations (i.e. normalization).
Definition: VectorFunction.hpp:21
Quaternion< T, Packed > Normalize(const Quaternion< T, Packed > &q)
Returns the unit quaternion of the same direction. Does not change this object.
Definition: QuaternionFunction.hpp:66
Represents a vector in N-dimensional space.
Definition: Definitions.hpp:57
T Dot(const Vector< T, Dim, Packed > &lhs, const Vector< T, Dim, Packed > &rhs)
Calculates the scalar product (dot product) of the two arguments.
Definition: VectorFunction.hpp:111
Definition: Approx.hpp:11
Vector< T, Dim, Packed > Max(const Vector< T, Dim, Packed > &lhs, const Vector< T, Dim, Packed > &rhs)
Returns the element-wise maximum of arguments
Definition: VectorFunction.hpp:176
Definition: Definitions.hpp:63
T LengthSquared(const Quaternion< T, Packed > &q)
Returns the square of the absolute value.
Definition: QuaternionFunction.hpp:53
constexpr int Dimension() const
Returns the number of dimensions of the vector.
Definition: VectorImpl.hpp:402
auto Cross(const Vector< T, Dim, Packed > &head, Args &&... args) -> Vector< T, Dim, Packed >
Returns the generalized cross-product in N dimensions.
Definition: VectorFunction.hpp:223
T Determinant(const Matrix< T, Dim, Dim, Order, Layout, Packed > &m)
Returns the determinant of the matrix.
Definition: MatrixFunction.hpp:21
Definition: Traits.hpp:218
constexpr T ConstexprAbs(T arg)
Definition: MathUtil.hpp:21
T Length(const Quaternion< T, Packed > &q)
Returns the absolute value of the quaternion.
Definition: QuaternionFunction.hpp:60
T LengthPrecise(const Vector< T, Dim, Packed > &v)
Returns the length of the vector, avoids overflow and underflow, so it&#39;s more expensive.
Definition: VectorFunction.hpp:41
Vector< T, Dim, Packed > SafeNormalize(const Vector< T, Dim, Packed > &v)
Makes a unit vector, but keeps direction. Leans towards (1,0,0...) for nullvectors, costs more.
Definition: VectorFunction.hpp:76
constexpr int RowCount() const
Returns the number of rows of the matrix.
Definition: MatrixImpl.hpp:31
T sign(T arg)
Definition: MathUtil.hpp:6
bool IsNormalized(const Quaternion< T, Packed > &q)
Check if the quaternion is a unit quaternion, with some tolerance for floats.
Definition: QuaternionFunction.hpp:78