Mat.h 14 KB

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