Mat.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #ifndef ANKI_MATH_MAT_H
  6. #define ANKI_MATH_MAT_H
  7. #include "anki/math/CommonIncludes.h"
  8. #include "anki/math/Vec.h"
  9. namespace anki {
  10. /// @addtogroup math
  11. /// @{
  12. /// Common code for all matrices
  13. /// @tparam T The scalar type. Eg float.
  14. /// @tparam J The number of rows.
  15. /// @tparam I The number of columns.
  16. /// @tparam TM The type of the derived class. Eg TMat3.
  17. /// @tparam TVJ The vector type of the row.
  18. /// @tparam TVI The vector type of the column.
  19. template<typename T, U J, U I, typename TSimd, typename TM, typename TVJ,
  20. typename TVI>
  21. class TMat
  22. {
  23. public:
  24. using Scalar = T;
  25. static constexpr U ROW_SIZE = J; ///< Number of rows
  26. static constexpr U COLUMN_SIZE = I; ///< Number of columns
  27. static constexpr U SIZE = J * I; ///< Number of total elements
  28. /// @name Constructors
  29. /// @{
  30. explicit TMat()
  31. {}
  32. TMat(const TMat& b)
  33. {
  34. for(U i = 0; i < N; i++)
  35. {
  36. m_arr1[i] = b.m_arr1[i];
  37. }
  38. }
  39. explicit TMat(const T f)
  40. {
  41. for(T& x : m_arr1)
  42. {
  43. x = f;
  44. }
  45. }
  46. explicit TMat(const T arr[])
  47. {
  48. for(U i = 0; i < N; i++)
  49. {
  50. m_arr1[i] = arr[i];
  51. }
  52. }
  53. /// @}
  54. /// @name Accessors
  55. /// @{
  56. T& operator()(const U j, const U i)
  57. {
  58. return m_arr2[j][i];
  59. }
  60. T operator()(const U j, const U i) const
  61. {
  62. return m_arr2[j][i];
  63. }
  64. T& operator[](const U n)
  65. {
  66. return m_arr1[n];
  67. }
  68. T operator[](const U n) const
  69. {
  70. return m_arr1[n];
  71. }
  72. /// @}
  73. /// @name Operators with same type
  74. /// @{
  75. TM& operator=(const TM& b)
  76. {
  77. for(U n = 0; n < N; n++)
  78. {
  79. m_arr1[n] = b.m_arr1[n];
  80. }
  81. return static_cast<TM&>(*this);
  82. }
  83. TM operator+(const TM& b) const
  84. {
  85. TM c;
  86. for(U n = 0; n < N; n++)
  87. {
  88. c.m_arr1[n] = m_arr1[n] + b.m_arr1[n];
  89. }
  90. return c;
  91. }
  92. TM& operator+=(const TM& b)
  93. {
  94. for(U n = 0; n < N; n++)
  95. {
  96. m_arr1[n] += b.m_arr1[n];
  97. }
  98. return static_cast<TM&>(*this);
  99. }
  100. TM operator-(const TM& b) const
  101. {
  102. TM c;
  103. for(U n = 0; n < N; n++)
  104. {
  105. c.m_arr1[n] = m_arr1[n] - b.m_arr1[n];
  106. }
  107. return c;
  108. }
  109. TM& operator-=(const TM& b)
  110. {
  111. for(U n = 0; n < N; n++)
  112. {
  113. m_arr1[n] -= b.m_arr1[n];
  114. }
  115. return static_cast<TM&>(*this);
  116. }
  117. TM operator*(const TM& b) const
  118. {
  119. static_assert(I == J, "Only for square matrices");
  120. TM out;
  121. const TMat& a = *this;
  122. for(U j = 0; j < J; j++)
  123. {
  124. for(U i = 0; i < I; i++)
  125. {
  126. out(j, i) = T(0);
  127. for(U k = 0; k < I; k++)
  128. {
  129. out(j, i) += a(j, k) * b(k, i);
  130. }
  131. }
  132. }
  133. return out;
  134. }
  135. TM& operator*=(const TM& b)
  136. {
  137. (*this) = (*this) * b;
  138. return static_cast<TM&>(*this);
  139. }
  140. Bool operator==(const TM& b) const
  141. {
  142. for(U i = 0; i < N; i++)
  143. {
  144. if(!isZero<T>(m_arr1[i] - b.m_arr1[i]))
  145. {
  146. return false;
  147. }
  148. }
  149. return true;
  150. }
  151. Bool operator!=(const TM& b) const
  152. {
  153. for(U i = 0; i < N; i++)
  154. {
  155. if(!isZero<T>(m_arr1[i] - b.m_arr1[i]))
  156. {
  157. return true;
  158. }
  159. }
  160. return false;
  161. }
  162. /// @}
  163. /// @name Operators with T
  164. /// @{
  165. TM operator+(const T f) const
  166. {
  167. TM out;
  168. for(U i = 0; i < N; i++)
  169. {
  170. out.m_arr1[i] = m_arr1[i] + f;
  171. }
  172. return out;
  173. }
  174. TM& operator+=(const T f)
  175. {
  176. for(U i = 0; i < N; i++)
  177. {
  178. m_arr1[i] += f;
  179. }
  180. return static_cast<TM&>(*this);
  181. }
  182. TM operator-(const T f) const
  183. {
  184. TM out;
  185. for(U i = 0; i < N; i++)
  186. {
  187. out.m_arr1[i] = m_arr1[i] - f;
  188. }
  189. return out;
  190. }
  191. TM& operator-=(const T f)
  192. {
  193. for(U i = 0; i < N; i++)
  194. {
  195. m_arr1[i] -= f;
  196. }
  197. return static_cast<TM&>(*this);
  198. }
  199. TM operator*(const T f) const
  200. {
  201. TM out;
  202. for(U i = 0; i < N; i++)
  203. {
  204. out.m_arr1[i] = m_arr1[i] * f;
  205. }
  206. return out;
  207. }
  208. TM& operator*=(const T f)
  209. {
  210. for(U i = 0; i < N; i++)
  211. {
  212. m_arr1[i] *= f;
  213. }
  214. return static_cast<TM&>(*this);
  215. }
  216. TM operator/(const T f) const
  217. {
  218. ANKI_ASSERT(f != T(0));
  219. TM out;
  220. for(U i = 0; i < N; i++)
  221. {
  222. out.m_arr1[i] = m_arr1[i] / f;
  223. }
  224. return out;
  225. }
  226. TM& operator/=(const T f)
  227. {
  228. ANKI_ASSERT(f != T(0));
  229. for(U i = 0; i < N; i++)
  230. {
  231. m_arr1[i] /= f;
  232. }
  233. return static_cast<TM&>(*this);
  234. }
  235. /// @}
  236. /// @name Operators with other types
  237. /// @{
  238. TVI operator*(const TVJ& v) const
  239. {
  240. const TMat& m = *this;
  241. TVI out;
  242. for(U j = 0; j < J; j++)
  243. {
  244. T sum = 0.0;
  245. for(U i = 0; i < I; i++)
  246. {
  247. sum += m(j, i) * v[i];
  248. }
  249. out[j] = sum;
  250. }
  251. return out;
  252. }
  253. /// @}
  254. /// @name Other
  255. /// @{
  256. void setRow(const U j, const TVJ& v)
  257. {
  258. for(U i = 0; i < I; i++)
  259. {
  260. m_arr2[j][i] = v[i];
  261. }
  262. }
  263. void setRows(const TVJ& a, const TVJ& b, const TVJ& c)
  264. {
  265. setRow(0, a);
  266. setRow(1, b);
  267. setRow(2, c);
  268. }
  269. void setRows(const TVJ& a, const TVJ& b, const TVJ& c, const TVJ& d)
  270. {
  271. static_assert(J > 3, "Wrong matrix");
  272. setRows(a, b, c);
  273. setRow(3, d);
  274. }
  275. TVJ getRow(const U j) const
  276. {
  277. TVJ out;
  278. for(U i = 0; i < I; i++)
  279. {
  280. out[i] = m_arr2[j][i];
  281. }
  282. return out;
  283. }
  284. void getRows(TVJ& a, TVJ& b, TVJ& c) const
  285. {
  286. a = getRow(0);
  287. b = getRow(1);
  288. c = getRow(2);
  289. }
  290. void getRows(TVJ& a, TVJ& b, TVJ& c, TVJ& d) const
  291. {
  292. static_assert(J > 3, "Wrong matrix");
  293. getRows(a, b, c);
  294. d = getRow(3);
  295. }
  296. void setColumn(const U i, const TVI& v)
  297. {
  298. for(U j = 0; j < J; j++)
  299. {
  300. m_arr2[j][i] = v[j];
  301. }
  302. }
  303. void setColumns(const TVI& a, const TVI& b, const TVI& c)
  304. {
  305. setColumn(0, a);
  306. setColumn(1, b);
  307. setColumn(2, c);
  308. }
  309. void setColumns(const TVI& a, const TVI& b, const TVI& c, const TVI& d)
  310. {
  311. static_assert(I > 3, "Check column number");
  312. setColumns(a, b, c);
  313. setColumn(3, d);
  314. }
  315. TVI getColumn(const U i) const
  316. {
  317. TVI out;
  318. for(U j = 0; j < J; j++)
  319. {
  320. out[j] = m_arr2[j][i];
  321. }
  322. return out;
  323. }
  324. void getColumns(TVI& a, TVI& b, TVI& c) const
  325. {
  326. a = getColumn(0);
  327. b = getColumn(1);
  328. c = getColumn(2);
  329. }
  330. void getColumns(TVI& a, TVI& b, TVI& c, TVI& d) const
  331. {
  332. static_assert(I > 3, "Check column number");
  333. getColumns(a, b, c);
  334. d = getColumn(3);
  335. }
  336. /// Get 1st column
  337. TVI getXAxis() const
  338. {
  339. return getColumn(0);
  340. }
  341. /// Get 2nd column
  342. TVI getYAxis() const
  343. {
  344. return getColumn(1);
  345. }
  346. /// Get 3rd column
  347. TVI getZAxis() const
  348. {
  349. return getColumn(2);
  350. }
  351. /// Set 1st column
  352. void setXAxis(const TVI& v)
  353. {
  354. setColumn(0, v);
  355. }
  356. /// Set 2nd column
  357. void setYAxis(const TVI& v)
  358. {
  359. setColumn(1, v);
  360. }
  361. /// Set 3rd column
  362. void setZAxis(const TVI& v)
  363. {
  364. setColumn(2, v);
  365. }
  366. void setRotationX(const T rad)
  367. {
  368. TMat& m = *this;
  369. T sintheta, costheta;
  370. sinCos(rad, sintheta, costheta);
  371. m(0, 0) = 1.0;
  372. m(0, 1) = 0.0;
  373. m(0, 2) = 0.0;
  374. m(1, 0) = 0.0;
  375. m(1, 1) = costheta;
  376. m(1, 2) = -sintheta;
  377. m(2, 0) = 0.0;
  378. m(2, 1) = sintheta;
  379. m(2, 2) = costheta;
  380. }
  381. void setRotationY(const T rad)
  382. {
  383. TMat& m = *this;
  384. T sintheta, costheta;
  385. sinCos(rad, sintheta, costheta);
  386. m(0, 0) = costheta;
  387. m(0, 1) = 0.0;
  388. m(0, 2) = sintheta;
  389. m(1, 0) = 0.0;
  390. m(1, 1) = 1.0;
  391. m(1, 2) = 0.0;
  392. m(2, 0) = -sintheta;
  393. m(2, 1) = 0.0;
  394. m(2, 2) = costheta;
  395. }
  396. void setRotationZ(const T rad)
  397. {
  398. TMat& m = *this;
  399. T sintheta, costheta;
  400. sinCos(rad, sintheta, costheta);
  401. m(0, 0) = costheta;
  402. m(0, 1) = -sintheta;
  403. m(0, 2) = 0.0;
  404. m(1, 0) = sintheta;
  405. m(1, 1) = costheta;
  406. m(1, 2) = 0.0;
  407. m(2, 0) = 0.0;
  408. m(2, 1) = 0.0;
  409. m(2, 2) = 1.0;
  410. }
  411. /// It rotates "this" in the axis defined by the rotation AND not the
  412. /// world axis
  413. void rotateXAxis(const T rad)
  414. {
  415. TMat& m = *this;
  416. // If we analize the mat3 we can extract the 3 unit vectors rotated by
  417. // the mat3. The 3 rotated vectors are in mat's columns. This means
  418. // that: mat3.colomn[0] == i * mat3. rotateXAxis() rotates rad angle
  419. // not from i vector (aka x axis) but from the vector from colomn 0
  420. // NOTE: See the clean code from < r664
  421. T sina, cosa;
  422. sinCos(rad, sina, cosa);
  423. // zAxis = zAxis*cosa - yAxis*sina;
  424. m(0, 2) = m(0, 2) * cosa - m(0, 1) * sina;
  425. m(1, 2) = m(1, 2) * cosa - m(1, 1) * sina;
  426. m(2, 2) = m(2, 2) * cosa - m(2, 1) * sina;
  427. // zAxis.normalize();
  428. T len = sqrt(m(0, 2) * m(0, 2)
  429. + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2));
  430. m(0, 2) /= len;
  431. m(1, 2) /= len;
  432. m(2, 2) /= len;
  433. // yAxis = zAxis * xAxis;
  434. m(0, 1) = m(1, 2) * m(2, 0) - m(2, 2) * m(1, 0);
  435. m(1, 1) = m(2, 2) * m(0, 0) - m(0, 2) * m(2, 0);
  436. m(2, 1) = m(0, 2) * m(1, 0) - m(1, 2) * m(0, 0);
  437. // yAxis.normalize();
  438. }
  439. /// @copybrief rotateXAxis
  440. void rotateYAxis(const T rad)
  441. {
  442. TMat& m = *this;
  443. // NOTE: See the clean code from < r664
  444. T sina, cosa;
  445. sinCos(rad, sina, cosa);
  446. // zAxis = zAxis*cosa + xAxis*sina;
  447. m(0, 2) = m(0, 2) * cosa + m(0, 0) * sina;
  448. m(1, 2) = m(1, 2) * cosa + m(1, 0) * sina;
  449. m(2, 2) = m(2, 2) * cosa + m(2, 0) * sina;
  450. // zAxis.normalize();
  451. T len = sqrt(m(0, 2) * m(0, 2)
  452. + m(1, 2) * m(1, 2) + m(2, 2) * m(2, 2));
  453. m(0, 2) /= len;
  454. m(1, 2) /= len;
  455. m(2, 2) /= len;
  456. // xAxis = (zAxis*yAxis) * -1.0f;
  457. m(0, 0) = m(2, 2) * m(1, 1) - m(1, 2) * m(2, 1);
  458. m(1, 0) = m(0, 2) * m(2, 1) - m(2, 2) * m(0, 1);
  459. m(2, 0) = m(1, 2) * m(0, 1) - m(0, 2) * m(1, 1);
  460. }
  461. /// @copybrief rotateXAxis
  462. void rotateZAxis(const T rad)
  463. {
  464. TMat& m = *this;
  465. // NOTE: See the clean code from < r664
  466. T sina, cosa;
  467. sinCos(rad, sina, cosa);
  468. // xAxis = xAxis*cosa + yAxis*sina;
  469. m(0, 0) = m(0, 0) * cosa + m(0, 1) * sina;
  470. m(1, 0) = m(1, 0) * cosa + m(1, 1) * sina;
  471. m(2, 0) = m(2, 0) * cosa + m(2, 1) * sina;
  472. // xAxis.normalize();
  473. T len = sqrt(m(0, 0) * m(0, 0)
  474. + m(1, 0) * m(1, 0) + m(2, 0) * m(2, 0));
  475. m(0, 0) /= len;
  476. m(1, 0) /= len;
  477. m(2, 0) /= len;
  478. // yAxis = zAxis*xAxis;
  479. m(0, 1) = m(1, 2) * m(2, 0) - m(2, 2) * m(1, 0);
  480. m(1, 1) = m(2, 2) * m(0, 0) - m(0, 2) * m(2, 0);
  481. m(2, 1) = m(0, 2) * m(1, 0) - m(1, 2) * m(0, 0);
  482. }
  483. void setRotationPart(const TMat3<T>& m3)
  484. {
  485. TMat& m = *this;
  486. for(U j = 0; j < 3; j++)
  487. {
  488. for(U i = 0; i < 3; i++)
  489. {
  490. m(j, i) = m3(j, i);
  491. }
  492. }
  493. }
  494. void setRotationPart(const TQuat<T>& q)
  495. {
  496. TMat& m = *this;
  497. // If length is > 1 + 0.002 or < 1 - 0.002 then not normalized quat
  498. ANKI_ASSERT(fabs(1.0 - q.getLength()) <= 0.002);
  499. T xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
  500. xs = q.x() + q.x();
  501. ys = q.y() + q.y();
  502. zs = q.z() + q.z();
  503. wx = q.w() * xs;
  504. wy = q.w() * ys;
  505. wz = q.w() * zs;
  506. xx = q.x() * xs;
  507. xy = q.x() * ys;
  508. xz = q.x() * zs;
  509. yy = q.y() * ys;
  510. yz = q.y() * zs;
  511. zz = q.z() * zs;
  512. m(0, 0) = 1.0 - (yy + zz);
  513. m(0, 1) = xy - wz;
  514. m(0, 2) = xz + wy;
  515. m(1, 0) = xy + wz;
  516. m(1, 1) = 1.0 - (xx + zz);
  517. m(1, 2) = yz - wx;
  518. m(2, 0) = xz - wy;
  519. m(2, 1) = yz + wx;
  520. m(2, 2) = 1.0 - (xx + yy);
  521. }
  522. void setRotationPart(const TEuler<T>& e)
  523. {
  524. TMat& m = *this;
  525. T ch, sh, ca, sa, cb, sb;
  526. sinCos(e.y(), sh, ch);
  527. sinCos(e.z(), sa, ca);
  528. sinCos(e.x(), sb, cb);
  529. m(0, 0) = ch * ca;
  530. m(0, 1) = sh * sb - ch * sa * cb;
  531. m(0, 2) = ch * sa * sb + sh * cb;
  532. m(1, 0) = sa;
  533. m(1, 1) = ca * cb;
  534. m(1, 2) = -ca * sb;
  535. m(2, 0) = -sh * ca;
  536. m(2, 1) = sh * sa * cb + ch * sb;
  537. m(2, 2) = -sh * sa * sb + ch * cb;
  538. }
  539. void setRotationPart(const TAxisang<T>& axisang)
  540. {
  541. TMat& m = *this;
  542. // Not normalized axis
  543. ANKI_ASSERT(isZero<T>(1.0 - axisang.getAxis().getLength()));
  544. T c, s;
  545. sinCos(axisang.getAngle(), s, c);
  546. T t = 1.0 - c;
  547. const TVec3<T>& axis = axisang.getAxis();
  548. m(0, 0) = c + axis.x() * axis.x() * t;
  549. m(1, 1) = c + axis.y() * axis.y() * t;
  550. m(2, 2) = c + axis.z() * axis.z() * t;
  551. T tmp1 = axis.x() * axis.y() * t;
  552. T tmp2 = axis.z() * s;
  553. m(1, 0) = tmp1 + tmp2;
  554. m(0, 1) = tmp1 - tmp2;
  555. tmp1 = axis.x() * axis.z() * t;
  556. tmp2 = axis.y() * s;
  557. m(2, 0) = tmp1 - tmp2;
  558. m(0, 2) = tmp1 + tmp2;
  559. tmp1 = axis.y() * axis.z() * t;
  560. tmp2 = axis.x() * s;
  561. m(2, 1) = tmp1 + tmp2;
  562. m(1, 2) = tmp1 - tmp2;
  563. }
  564. TMat3<T> getRotationPart() const
  565. {
  566. const TMat& m = *this;
  567. TMat3<T> m3;
  568. m3(0, 0) = m(0, 0);
  569. m3(0, 1) = m(0, 1);
  570. m3(0, 2) = m(0, 2);
  571. m3(1, 0) = m(1, 0);
  572. m3(1, 1) = m(1, 1);
  573. m3(1, 2) = m(1, 2);
  574. m3(2, 0) = m(2, 0);
  575. m3(2, 1) = m(2, 1);
  576. m3(2, 2) = m(2, 2);
  577. return m3;
  578. }
  579. void setTranslationPart(const TVI& v)
  580. {
  581. if(ROW_SIZE == 4)
  582. {
  583. ANKI_ASSERT(isZero<T>(v[3] - static_cast<T>(1))
  584. && "w should be 1");
  585. }
  586. setColumn(3, v);
  587. }
  588. TVI getTranslationPart() const
  589. {
  590. return getColumn(3);
  591. }
  592. void reorthogonalize()
  593. {
  594. // There are 2 methods, the standard and the Gram-Schmidt method with a
  595. // twist for zAxis. This uses the 2nd. For the first see < r664
  596. TVI xAxis, yAxis, zAxis;
  597. getColumns(xAxis, yAxis, zAxis);
  598. xAxis.normalize();
  599. yAxis = yAxis - (xAxis * xAxis.dot(yAxis));
  600. yAxis.normalize();
  601. zAxis = xAxis.cross(yAxis);
  602. setColumns(xAxis, yAxis, zAxis);
  603. }
  604. void transpose()
  605. {
  606. static_assert(I == J, "Only for square matrices");
  607. for(U j = 0; j < J; j++)
  608. {
  609. for(U i = j + 1; i < I; i++)
  610. {
  611. T tmp = m_arr2[j][i];
  612. m_arr2[j][i] = m_arr2[i][j];
  613. m_arr2[i][j] = tmp;
  614. }
  615. }
  616. }
  617. void transposeRotationPart()
  618. {
  619. for(U j = 0; j < 3; j++)
  620. {
  621. for(U i = j + 1; i < 3; i++)
  622. {
  623. T tmp = m_arr2[j][i];
  624. m_arr2[j][i] = m_arr2[i][j];
  625. m_arr2[i][j] = tmp;
  626. }
  627. }
  628. }
  629. TM getTransposed() const
  630. {
  631. static_assert(I == J, "Only for square matrices");
  632. TM out;
  633. for(U j = 0; j < J; j++)
  634. {
  635. for(U i = 0; i < I; i++)
  636. {
  637. out.m_arr2[i][j] = m_arr2[j][i];
  638. }
  639. }
  640. return out;
  641. }
  642. TMat lerp(const TMat& b, T t) const
  643. {
  644. return ((*this) * (1.0 - t)) + (b * t);
  645. }
  646. static const TM& getZero()
  647. {
  648. static const TM zero(0.0);
  649. return zero;
  650. }
  651. void setZero()
  652. {
  653. *this = getZero();
  654. }
  655. template<typename TAlloc>
  656. String toString(TAlloc alloc) const
  657. {
  658. // TODO
  659. ANKI_ASSERT(0 && "TODO");
  660. return String();
  661. }
  662. /// @}
  663. protected:
  664. static constexpr U N = I * J;
  665. /// @name Data members
  666. /// @{
  667. union
  668. {
  669. Array<T, N> m_arr1;
  670. Array2d<T, J, I> m_arr2;
  671. T m_carr1[N]; ///< For easier debugging with gdb
  672. T m_carr2[J][I]; ///< For easier debugging with gdb
  673. TSimd m_simd;
  674. };
  675. /// @}
  676. };
  677. /// @}
  678. } // end namespace anki
  679. #endif