Vector.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Math.h>
  9. #include <algorithm>
  10. #include <array>
  11. #include <initializer_list>
  12. namespace WwiseGTE
  13. {
  14. template <int N, typename Real>
  15. class Vector
  16. {
  17. public:
  18. // The tuple is uninitialized.
  19. Vector() = default;
  20. // The tuple is fully initialized by the inputs.
  21. Vector(std::array<Real, N> const& values)
  22. :
  23. mTuple(values)
  24. {
  25. }
  26. // At most N elements are copied from the initializer list, setting
  27. // any remaining elements to zero. Create the zero vector using the
  28. // syntax
  29. // Vector<N,Real> zero{(Real)0};
  30. // WARNING: The C++ 11 specification states that
  31. // Vector<N,Real> zero{};
  32. // will lead to a call of the default constructor, not the initializer
  33. // constructor!
  34. Vector(std::initializer_list<Real> values)
  35. {
  36. int const numValues = static_cast<int>(values.size());
  37. if (N == numValues)
  38. {
  39. std::copy(values.begin(), values.end(), mTuple.begin());
  40. }
  41. else if (N > numValues)
  42. {
  43. std::copy(values.begin(), values.end(), mTuple.begin());
  44. std::fill(mTuple.begin() + numValues, mTuple.end(), (Real)0);
  45. }
  46. else // N < numValues
  47. {
  48. std::copy(values.begin(), values.begin() + N, mTuple.begin());
  49. }
  50. }
  51. // For 0 <= d < N, element d is 1 and all others are 0. If d is
  52. // invalid, the zero vector is created. This is a convenience for
  53. // creating the standard Euclidean basis vectors; see also
  54. // MakeUnit(int) and Unit(int).
  55. Vector(int d)
  56. {
  57. MakeUnit(d);
  58. }
  59. // The copy constructor, destructor, and assignment operator are
  60. // generated by the compiler.
  61. // Member access. The first operator[] returns a const reference
  62. // rather than a Real value. This supports writing via standard file
  63. // operations that require a const pointer to data.
  64. inline int GetSize() const
  65. {
  66. return N;
  67. }
  68. inline Real const& operator[](int i) const
  69. {
  70. return mTuple[i];
  71. }
  72. inline Real& operator[](int i)
  73. {
  74. return mTuple[i];
  75. }
  76. // Comparisons for sorted containers and geometric ordering.
  77. inline bool operator==(Vector const& vec) const
  78. {
  79. return mTuple == vec.mTuple;
  80. }
  81. inline bool operator!=(Vector const& vec) const
  82. {
  83. return mTuple != vec.mTuple;
  84. }
  85. inline bool operator< (Vector const& vec) const
  86. {
  87. return mTuple < vec.mTuple;
  88. }
  89. inline bool operator<=(Vector const& vec) const
  90. {
  91. return mTuple <= vec.mTuple;
  92. }
  93. inline bool operator> (Vector const& vec) const
  94. {
  95. return mTuple > vec.mTuple;
  96. }
  97. inline bool operator>=(Vector const& vec) const
  98. {
  99. return mTuple >= vec.mTuple;
  100. }
  101. // Special vectors.
  102. // All components are 0.
  103. void MakeZero()
  104. {
  105. std::fill(mTuple.begin(), mTuple.end(), (Real)0);
  106. }
  107. // All components are 1.
  108. void MakeOnes()
  109. {
  110. std::fill(mTuple.begin(), mTuple.end(), (Real)1);
  111. }
  112. // Component d is 1, all others are zero.
  113. void MakeUnit(int d)
  114. {
  115. std::fill(mTuple.begin(), mTuple.end(), (Real)0);
  116. if (0 <= d && d < N)
  117. {
  118. mTuple[d] = (Real)1;
  119. }
  120. }
  121. static Vector Zero()
  122. {
  123. Vector<N, Real> v;
  124. v.MakeZero();
  125. return v;
  126. }
  127. static Vector Ones()
  128. {
  129. Vector<N, Real> v;
  130. v.MakeOnes();
  131. return v;
  132. }
  133. static Vector Unit(int d)
  134. {
  135. Vector<N, Real> v;
  136. v.MakeUnit(d);
  137. return v;
  138. }
  139. protected:
  140. // This data structure takes advantage of the built-in operator[],
  141. // range checking, and visualizers in MSVS.
  142. std::array<Real, N> mTuple;
  143. };
  144. // Unary operations.
  145. template <int N, typename Real>
  146. Vector<N, Real> operator+(Vector<N, Real> const& v)
  147. {
  148. return v;
  149. }
  150. template <int N, typename Real>
  151. Vector<N, Real> operator-(Vector<N, Real> const& v)
  152. {
  153. Vector<N, Real> result;
  154. for (int i = 0; i < N; ++i)
  155. {
  156. result[i] = -v[i];
  157. }
  158. return result;
  159. }
  160. // Linear-algebraic operations.
  161. template <int N, typename Real>
  162. Vector<N, Real> operator+(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  163. {
  164. Vector<N, Real> result = v0;
  165. return result += v1;
  166. }
  167. template <int N, typename Real>
  168. Vector<N, Real> operator-(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  169. {
  170. Vector<N, Real> result = v0;
  171. return result -= v1;
  172. }
  173. template <int N, typename Real>
  174. Vector<N, Real> operator*(Vector<N, Real> const& v, Real scalar)
  175. {
  176. Vector<N, Real> result = v;
  177. return result *= scalar;
  178. }
  179. template <int N, typename Real>
  180. Vector<N, Real> operator*(Real scalar, Vector<N, Real> const& v)
  181. {
  182. Vector<N, Real> result = v;
  183. return result *= scalar;
  184. }
  185. template <int N, typename Real>
  186. Vector<N, Real> operator/(Vector<N, Real> const& v, Real scalar)
  187. {
  188. Vector<N, Real> result = v;
  189. return result /= scalar;
  190. }
  191. template <int N, typename Real>
  192. Vector<N, Real>& operator+=(Vector<N, Real>& v0, Vector<N, Real> const& v1)
  193. {
  194. for (int i = 0; i < N; ++i)
  195. {
  196. v0[i] += v1[i];
  197. }
  198. return v0;
  199. }
  200. template <int N, typename Real>
  201. Vector<N, Real>& operator-=(Vector<N, Real>& v0, Vector<N, Real> const& v1)
  202. {
  203. for (int i = 0; i < N; ++i)
  204. {
  205. v0[i] -= v1[i];
  206. }
  207. return v0;
  208. }
  209. template <int N, typename Real>
  210. Vector<N, Real>& operator*=(Vector<N, Real>& v, Real scalar)
  211. {
  212. for (int i = 0; i < N; ++i)
  213. {
  214. v[i] *= scalar;
  215. }
  216. return v;
  217. }
  218. template <int N, typename Real>
  219. Vector<N, Real>& operator/=(Vector<N, Real>& v, Real scalar)
  220. {
  221. if (scalar != (Real)0)
  222. {
  223. Real invScalar = (Real)1 / scalar;
  224. for (int i = 0; i < N; ++i)
  225. {
  226. v[i] *= invScalar;
  227. }
  228. }
  229. else
  230. {
  231. for (int i = 0; i < N; ++i)
  232. {
  233. v[i] = (Real)0;
  234. }
  235. }
  236. return v;
  237. }
  238. // Componentwise algebraic operations.
  239. template <int N, typename Real>
  240. Vector<N, Real> operator*(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  241. {
  242. Vector<N, Real> result = v0;
  243. return result *= v1;
  244. }
  245. template <int N, typename Real>
  246. Vector<N, Real> operator/(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  247. {
  248. Vector<N, Real> result = v0;
  249. return result /= v1;
  250. }
  251. template <int N, typename Real>
  252. Vector<N, Real>& operator*=(Vector<N, Real>& v0, Vector<N, Real> const& v1)
  253. {
  254. for (int i = 0; i < N; ++i)
  255. {
  256. v0[i] *= v1[i];
  257. }
  258. return v0;
  259. }
  260. template <int N, typename Real>
  261. Vector<N, Real>& operator/=(Vector<N, Real>& v0, Vector<N, Real> const& v1)
  262. {
  263. for (int i = 0; i < N; ++i)
  264. {
  265. v0[i] /= v1[i];
  266. }
  267. return v0;
  268. }
  269. // Geometric operations. The functions with 'robust' set to 'false' use
  270. // the standard algorithm for normalizing a vector by computing the length
  271. // as a square root of the squared length and dividing by it. The results
  272. // can be infinite (or NaN) if the length is zero. When 'robust' is set
  273. // to 'true', the algorithm is designed to avoid floating-point overflow
  274. // and sets the normalized vector to zero when the length is zero.
  275. template <int N, typename Real>
  276. Real Dot(Vector<N, Real> const& v0, Vector<N, Real> const& v1)
  277. {
  278. Real dot = v0[0] * v1[0];
  279. for (int i = 1; i < N; ++i)
  280. {
  281. dot += v0[i] * v1[i];
  282. }
  283. return dot;
  284. }
  285. template <int N, typename Real>
  286. Real Length(Vector<N, Real> const& v, bool robust = false)
  287. {
  288. if (robust)
  289. {
  290. Real maxAbsComp = std::fabs(v[0]);
  291. for (int i = 1; i < N; ++i)
  292. {
  293. Real absComp = std::fabs(v[i]);
  294. if (absComp > maxAbsComp)
  295. {
  296. maxAbsComp = absComp;
  297. }
  298. }
  299. Real length;
  300. if (maxAbsComp > (Real)0)
  301. {
  302. Vector<N, Real> scaled = v / maxAbsComp;
  303. length = maxAbsComp * std::sqrt(Dot(scaled, scaled));
  304. }
  305. else
  306. {
  307. length = (Real)0;
  308. }
  309. return length;
  310. }
  311. else
  312. {
  313. return std::sqrt(Dot(v, v));
  314. }
  315. }
  316. template <int N, typename Real>
  317. Real Normalize(Vector<N, Real>& v, bool robust = false)
  318. {
  319. if (robust)
  320. {
  321. Real maxAbsComp = std::fabs(v[0]);
  322. for (int i = 1; i < N; ++i)
  323. {
  324. Real absComp = std::fabs(v[i]);
  325. if (absComp > maxAbsComp)
  326. {
  327. maxAbsComp = absComp;
  328. }
  329. }
  330. Real length;
  331. if (maxAbsComp > (Real)0)
  332. {
  333. v /= maxAbsComp;
  334. length = std::sqrt(Dot(v, v));
  335. v /= length;
  336. length *= maxAbsComp;
  337. }
  338. else
  339. {
  340. length = (Real)0;
  341. for (int i = 0; i < N; ++i)
  342. {
  343. v[i] = (Real)0;
  344. }
  345. }
  346. return length;
  347. }
  348. else
  349. {
  350. Real length = std::sqrt(Dot(v, v));
  351. if (length > (Real)0)
  352. {
  353. v /= length;
  354. }
  355. else
  356. {
  357. for (int i = 0; i < N; ++i)
  358. {
  359. v[i] = (Real)0;
  360. }
  361. }
  362. return length;
  363. }
  364. }
  365. // Gram-Schmidt orthonormalization to generate orthonormal vectors from
  366. // the linearly independent inputs. The function returns the smallest
  367. // length of the unnormalized vectors computed during the process. If
  368. // this value is nearly zero, it is possible that the inputs are linearly
  369. // dependent (within numerical round-off errors). On input,
  370. // 1 <= numElements <= N and v[0] through v[numElements-1] must be
  371. // initialized. On output, the vectors v[0] through v[numElements-1]
  372. // form an orthonormal set.
  373. template <int N, typename Real>
  374. Real Orthonormalize(int numInputs, Vector<N, Real>* v, bool robust = false)
  375. {
  376. if (v && 1 <= numInputs && numInputs <= N)
  377. {
  378. Real minLength = Normalize(v[0], robust);
  379. for (int i = 1; i < numInputs; ++i)
  380. {
  381. for (int j = 0; j < i; ++j)
  382. {
  383. Real dot = Dot(v[i], v[j]);
  384. v[i] -= v[j] * dot;
  385. }
  386. Real length = Normalize(v[i], robust);
  387. if (length < minLength)
  388. {
  389. minLength = length;
  390. }
  391. }
  392. return minLength;
  393. }
  394. return (Real)0;
  395. }
  396. // Construct a single vector orthogonal to the nonzero input vector. If
  397. // the maximum absolute component occurs at index i, then the orthogonal
  398. // vector U has u[i] = v[i+1], u[i+1] = -v[i], and all other components
  399. // zero. The index addition i+1 is computed modulo N.
  400. template <int N, typename Real>
  401. Vector<N, Real> GetOrthogonal(Vector<N, Real> const& v, bool unitLength)
  402. {
  403. Real cmax = std::fabs(v[0]);
  404. int imax = 0;
  405. for (int i = 1; i < N; ++i)
  406. {
  407. Real c = std::fabs(v[i]);
  408. if (c > cmax)
  409. {
  410. cmax = c;
  411. imax = i;
  412. }
  413. }
  414. Vector<N, Real> result;
  415. result.MakeZero();
  416. int inext = imax + 1;
  417. if (inext == N)
  418. {
  419. inext = 0;
  420. }
  421. result[imax] = v[inext];
  422. result[inext] = -v[imax];
  423. if (unitLength)
  424. {
  425. Real sqrDistance = result[imax] * result[imax] + result[inext] * result[inext];
  426. Real invLength = ((Real)1) / std::sqrt(sqrDistance);
  427. result[imax] *= invLength;
  428. result[inext] *= invLength;
  429. }
  430. return result;
  431. }
  432. // Compute the axis-aligned bounding box of the vectors. The return value
  433. // is 'true' iff the inputs are valid, in which case vmin and vmax have
  434. // valid values.
  435. template <int N, typename Real>
  436. bool ComputeExtremes(int numVectors, Vector<N, Real> const* v,
  437. Vector<N, Real>& vmin, Vector<N, Real>& vmax)
  438. {
  439. if (v && numVectors > 0)
  440. {
  441. vmin = v[0];
  442. vmax = vmin;
  443. for (int j = 1; j < numVectors; ++j)
  444. {
  445. Vector<N, Real> const& vec = v[j];
  446. for (int i = 0; i < N; ++i)
  447. {
  448. if (vec[i] < vmin[i])
  449. {
  450. vmin[i] = vec[i];
  451. }
  452. else if (vec[i] > vmax[i])
  453. {
  454. vmax[i] = vec[i];
  455. }
  456. }
  457. }
  458. return true;
  459. }
  460. return false;
  461. }
  462. // Lift n-tuple v to homogeneous (n+1)-tuple (v,last).
  463. template <int N, typename Real>
  464. Vector<N + 1, Real> HLift(Vector<N, Real> const& v, Real last)
  465. {
  466. Vector<N + 1, Real> result;
  467. for (int i = 0; i < N; ++i)
  468. {
  469. result[i] = v[i];
  470. }
  471. result[N] = last;
  472. return result;
  473. }
  474. // Project homogeneous n-tuple v = (u,v[n-1]) to (n-1)-tuple u.
  475. template <int N, typename Real>
  476. Vector<N - 1, Real> HProject(Vector<N, Real> const& v)
  477. {
  478. static_assert(N >= 2, "Invalid dimension.");
  479. Vector<N - 1, Real> result;
  480. for (int i = 0; i < N - 1; ++i)
  481. {
  482. result[i] = v[i];
  483. }
  484. return result;
  485. }
  486. // Lift n-tuple v = (w0,w1) to (n+1)-tuple u = (w0,u[inject],w1). By
  487. // inference, w0 is a (inject)-tuple [nonexistent when inject=0] and w1 is
  488. // a (n-inject)-tuple [nonexistent when inject=n].
  489. template <int N, typename Real>
  490. Vector<N + 1, Real> Lift(Vector<N, Real> const& v, int inject, Real value)
  491. {
  492. Vector<N + 1, Real> result;
  493. int i;
  494. for (i = 0; i < inject; ++i)
  495. {
  496. result[i] = v[i];
  497. }
  498. result[i] = value;
  499. int j = i;
  500. for (++j; i < N; ++i, ++j)
  501. {
  502. result[j] = v[i];
  503. }
  504. return result;
  505. }
  506. // Project n-tuple v = (w0,v[reject],w1) to (n-1)-tuple u = (w0,w1). By
  507. // inference, w0 is a (reject)-tuple [nonexistent when reject=0] and w1 is
  508. // a (n-1-reject)-tuple [nonexistent when reject=n-1].
  509. template <int N, typename Real>
  510. Vector<N - 1, Real> Project(Vector<N, Real> const& v, int reject)
  511. {
  512. static_assert(N >= 2, "Invalid dimension.");
  513. Vector<N - 1, Real> result;
  514. for (int i = 0, j = 0; i < N - 1; ++i, ++j)
  515. {
  516. if (j == reject)
  517. {
  518. ++j;
  519. }
  520. result[i] = v[j];
  521. }
  522. return result;
  523. }
  524. }