Matrix.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  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/Vector.h>
  9. #include <Mathematics/GaussianElimination.h>
  10. namespace WwiseGTE
  11. {
  12. template <int NumRows, int NumCols, typename Real>
  13. class Matrix
  14. {
  15. public:
  16. // The table is initialized to zero.
  17. Matrix()
  18. {
  19. MakeZero();
  20. }
  21. // The table is fully initialized by the inputs. The 'values' must be
  22. // specified in row-major order, regardless of the active storage
  23. // scheme (GTE_USE_ROW_MAJOR or GTE_USE_COL_MAJOR).
  24. Matrix(std::array<Real, NumRows * NumCols> const& values)
  25. {
  26. for (int r = 0, i = 0; r < NumRows; ++r)
  27. {
  28. for (int c = 0; c < NumCols; ++c, ++i)
  29. {
  30. mTable(r, c) = values[i];
  31. }
  32. }
  33. }
  34. // At most NumRows*NumCols are copied from the initializer list,
  35. // setting any remaining elements to zero. The 'values' must be
  36. // specified in row-major order, regardless of the active storage
  37. // scheme (GTE_USE_ROW_MAJOR or GTE_USE_COL_MAJOR). Create the zero
  38. // matrix using the syntax
  39. // Matrix<NumRows,NumCols,Real> zero{(Real)0};
  40. // WARNING: The C++ 11 specification states that
  41. // Matrix<NumRows,NumCols,Real> zero{};
  42. // will lead to a call of the default constructor, not the initializer
  43. // constructor!
  44. Matrix(std::initializer_list<Real> values)
  45. {
  46. int const numValues = static_cast<int>(values.size());
  47. auto iter = values.begin();
  48. int r, c, i;
  49. for (r = 0, i = 0; r < NumRows; ++r)
  50. {
  51. for (c = 0; c < NumCols; ++c, ++i)
  52. {
  53. if (i < numValues)
  54. {
  55. mTable(r, c) = *iter++;
  56. }
  57. else
  58. {
  59. break;
  60. }
  61. }
  62. if (c < NumCols)
  63. {
  64. // Fill in the remaining columns of the current row with zeros.
  65. for (/**/; c < NumCols; ++c)
  66. {
  67. mTable(r, c) = (Real)0;
  68. }
  69. ++r;
  70. break;
  71. }
  72. }
  73. if (r < NumRows)
  74. {
  75. // Fill in the remain rows with zeros.
  76. for (/**/; r < NumRows; ++r)
  77. {
  78. for (c = 0; c < NumCols; ++c)
  79. {
  80. mTable(r, c) = (Real)0;
  81. }
  82. }
  83. }
  84. }
  85. // For 0 <= r < NumRows and 0 <= c < NumCols, element (r,c) is 1 and
  86. // all others are 0. If either of r or c is invalid, the zero matrix
  87. // is created. This is a convenience for creating the standard
  88. // Euclidean basis matrices; see also MakeUnit(int,int) and
  89. // Unit(int,int).
  90. Matrix(int r, int c)
  91. {
  92. MakeUnit(r, c);
  93. }
  94. // The copy constructor, destructor, and assignment operator are
  95. // generated by the compiler.
  96. // Member access for which the storage representation is transparent.
  97. // The matrix entry in row r and column c is A(r,c). The first
  98. // operator() returns a const reference rather than a Real value.
  99. // This supports writing via standard file operations that require a
  100. // const pointer to data.
  101. inline Real const& operator()(int r, int c) const
  102. {
  103. return mTable(r, c);
  104. }
  105. inline Real& operator()(int r, int c)
  106. {
  107. return mTable(r, c);
  108. }
  109. // Member access by rows or by columns.
  110. void SetRow(int r, Vector<NumCols, Real> const& vec)
  111. {
  112. for (int c = 0; c < NumCols; ++c)
  113. {
  114. mTable(r, c) = vec[c];
  115. }
  116. }
  117. void SetCol(int c, Vector<NumRows, Real> const& vec)
  118. {
  119. for (int r = 0; r < NumRows; ++r)
  120. {
  121. mTable(r, c) = vec[r];
  122. }
  123. }
  124. Vector<NumCols, Real> GetRow(int r) const
  125. {
  126. Vector<NumCols, Real> vec;
  127. for (int c = 0; c < NumCols; ++c)
  128. {
  129. vec[c] = mTable(r, c);
  130. }
  131. return vec;
  132. }
  133. Vector<NumRows, Real> GetCol(int c) const
  134. {
  135. Vector<NumRows, Real> vec;
  136. for (int r = 0; r < NumRows; ++r)
  137. {
  138. vec[r] = mTable(r, c);
  139. }
  140. return vec;
  141. }
  142. // Member access by 1-dimensional index. NOTE: These accessors are
  143. // useful for the manipulation of matrix entries when it does not
  144. // matter whether storage is row-major or column-major. Do not use
  145. // constructs such as M[c+NumCols*r] or M[r+NumRows*c] that expose the
  146. // storage convention.
  147. inline Real const& operator[](int i) const
  148. {
  149. return mTable[i];
  150. }
  151. inline Real& operator[](int i)
  152. {
  153. return mTable[i];
  154. }
  155. // Comparisons for sorted containers and geometric ordering.
  156. inline bool operator==(Matrix const& mat) const
  157. {
  158. return mTable.mStorage == mat.mTable.mStorage;
  159. }
  160. inline bool operator!=(Matrix const& mat) const
  161. {
  162. return mTable.mStorage != mat.mTable.mStorage;
  163. }
  164. inline bool operator< (Matrix const& mat) const
  165. {
  166. return mTable.mStorage < mat.mTable.mStorage;
  167. }
  168. inline bool operator<=(Matrix const& mat) const
  169. {
  170. return mTable.mStorage <= mat.mTable.mStorage;
  171. }
  172. inline bool operator> (Matrix const& mat) const
  173. {
  174. return mTable.mStorage > mat.mTable.mStorage;
  175. }
  176. inline bool operator>=(Matrix const& mat) const
  177. {
  178. return mTable.mStorage >= mat.mTable.mStorage;
  179. }
  180. // Special matrices.
  181. // All components are 0.
  182. void MakeZero()
  183. {
  184. Real const zero(0);
  185. for (int i = 0; i < NumRows * NumCols; ++i)
  186. {
  187. mTable[i] = zero;
  188. }
  189. }
  190. // Component (r,c) is 1, all others zero.
  191. void MakeUnit(int r, int c)
  192. {
  193. MakeZero();
  194. if (0 <= r && r < NumRows && 0 <= c && c < NumCols)
  195. {
  196. mTable(r, c) = (Real)1;
  197. }
  198. }
  199. // Diagonal entries 1, others 0, even when nonsquare
  200. void MakeIdentity()
  201. {
  202. MakeZero();
  203. int const numDiagonal = (NumRows <= NumCols ? NumRows : NumCols);
  204. for (int i = 0; i < numDiagonal; ++i)
  205. {
  206. mTable(i, i) = (Real)1;
  207. }
  208. }
  209. static Matrix Zero()
  210. {
  211. Matrix M;
  212. M.MakeZero();
  213. return M;
  214. }
  215. static Matrix Unit(int r, int c)
  216. {
  217. Matrix M;
  218. M.MakeUnit(r, c);
  219. return M;
  220. }
  221. static Matrix Identity()
  222. {
  223. Matrix M;
  224. M.MakeIdentity();
  225. return M;
  226. }
  227. protected:
  228. class Table
  229. {
  230. public:
  231. // Storage-order-independent element access as 2D array.
  232. inline Real const& operator()(int r, int c) const
  233. {
  234. #if defined(GTE_USE_ROW_MAJOR)
  235. return mStorage[r][c];
  236. #else
  237. return mStorage[c][r];
  238. #endif
  239. }
  240. inline Real& operator()(int r, int c)
  241. {
  242. #if defined(GTE_USE_ROW_MAJOR)
  243. return mStorage[r][c];
  244. #else
  245. return mStorage[c][r];
  246. #endif
  247. }
  248. // Element access as 1D array. Use this internally only when
  249. // the 2D storage order is not relevant.
  250. inline Real const& operator[](int i) const
  251. {
  252. Real const* elements = &mStorage[0][0];
  253. return elements[i];
  254. }
  255. inline Real& operator[](int i)
  256. {
  257. Real* elements = &mStorage[0][0];
  258. return elements[i];
  259. }
  260. #if defined(GTE_USE_ROW_MAJOR)
  261. std::array<std::array<Real, NumCols>, NumRows> mStorage;
  262. #else
  263. std::array<std::array<Real, NumRows>, NumCols> mStorage;
  264. #endif
  265. };
  266. Table mTable;
  267. };
  268. // Unary operations.
  269. template <int NumRows, int NumCols, typename Real>
  270. Matrix<NumRows, NumCols, Real> operator+(Matrix<NumRows, NumCols, Real> const& M)
  271. {
  272. return M;
  273. }
  274. template <int NumRows, int NumCols, typename Real>
  275. Matrix<NumRows, NumCols, Real> operator-(Matrix<NumRows, NumCols, Real> const& M)
  276. {
  277. Matrix<NumRows, NumCols, Real> result;
  278. for (int i = 0; i < NumRows * NumCols; ++i)
  279. {
  280. result[i] = -M[i];
  281. }
  282. return result;
  283. }
  284. // Linear-algebraic operations.
  285. template <int NumRows, int NumCols, typename Real>
  286. Matrix<NumRows, NumCols, Real> operator+(
  287. Matrix<NumRows, NumCols, Real> const& M0,
  288. Matrix<NumRows, NumCols, Real> const& M1)
  289. {
  290. Matrix<NumRows, NumCols, Real> result = M0;
  291. return result += M1;
  292. }
  293. template <int NumRows, int NumCols, typename Real>
  294. Matrix<NumRows, NumCols, Real> operator-(
  295. Matrix<NumRows, NumCols, Real> const& M0,
  296. Matrix<NumRows, NumCols, Real> const& M1)
  297. {
  298. Matrix<NumRows, NumCols, Real> result = M0;
  299. return result -= M1;
  300. }
  301. template <int NumRows, int NumCols, typename Real>
  302. Matrix<NumRows, NumCols, Real> operator*(
  303. Matrix<NumRows, NumCols, Real> const& M, Real scalar)
  304. {
  305. Matrix<NumRows, NumCols, Real> result = M;
  306. return result *= scalar;
  307. }
  308. template <int NumRows, int NumCols, typename Real>
  309. Matrix<NumRows, NumCols, Real> operator*(
  310. Real scalar, Matrix<NumRows, NumCols, Real> const& M)
  311. {
  312. Matrix<NumRows, NumCols, Real> result = M;
  313. return result *= scalar;
  314. }
  315. template <int NumRows, int NumCols, typename Real>
  316. Matrix<NumRows, NumCols, Real> operator/(
  317. Matrix<NumRows, NumCols, Real> const& M, Real scalar)
  318. {
  319. Matrix<NumRows, NumCols, Real> result = M;
  320. return result /= scalar;
  321. }
  322. template <int NumRows, int NumCols, typename Real>
  323. Matrix<NumRows, NumCols, Real>& operator+=(
  324. Matrix<NumRows, NumCols, Real>& M0,
  325. Matrix<NumRows, NumCols, Real> const& M1)
  326. {
  327. for (int i = 0; i < NumRows * NumCols; ++i)
  328. {
  329. M0[i] += M1[i];
  330. }
  331. return M0;
  332. }
  333. template <int NumRows, int NumCols, typename Real>
  334. Matrix<NumRows, NumCols, Real>& operator-=(
  335. Matrix<NumRows, NumCols, Real>& M0,
  336. Matrix<NumRows, NumCols, Real> const& M1)
  337. {
  338. for (int i = 0; i < NumRows * NumCols; ++i)
  339. {
  340. M0[i] -= M1[i];
  341. }
  342. return M0;
  343. }
  344. template <int NumRows, int NumCols, typename Real>
  345. Matrix<NumRows, NumCols, Real>& operator*=(
  346. Matrix<NumRows, NumCols, Real>& M, Real scalar)
  347. {
  348. for (int i = 0; i < NumRows * NumCols; ++i)
  349. {
  350. M[i] *= scalar;
  351. }
  352. return M;
  353. }
  354. template <int NumRows, int NumCols, typename Real>
  355. Matrix<NumRows, NumCols, Real>& operator/=(
  356. Matrix<NumRows, NumCols, Real>& M, Real scalar)
  357. {
  358. if (scalar != (Real)0)
  359. {
  360. Real invScalar = ((Real)1) / scalar;
  361. for (int i = 0; i < NumRows * NumCols; ++i)
  362. {
  363. M[i] *= invScalar;
  364. }
  365. }
  366. else
  367. {
  368. for (int i = 0; i < NumRows * NumCols; ++i)
  369. {
  370. M[i] = (Real)0;
  371. }
  372. }
  373. return M;
  374. }
  375. // Geometric operations.
  376. template <int NumRows, int NumCols, typename Real>
  377. Real L1Norm(Matrix<NumRows, NumCols, Real> const& M)
  378. {
  379. Real sum = std::fabs(M[0]);
  380. for (int i = 1; i < NumRows * NumCols; ++i)
  381. {
  382. sum += std::fabs(M[i]);
  383. }
  384. return sum;
  385. }
  386. template <int NumRows, int NumCols, typename Real>
  387. Real L2Norm(Matrix<NumRows, NumCols, Real> const& M)
  388. {
  389. Real sum = M[0] * M[0];
  390. for (int i = 1; i < NumRows * NumCols; ++i)
  391. {
  392. sum += M[i] * M[i];
  393. }
  394. return std::sqrt(sum);
  395. }
  396. template <int NumRows, int NumCols, typename Real>
  397. Real LInfinityNorm(Matrix<NumRows, NumCols, Real> const& M)
  398. {
  399. Real maxAbsElement = M[0];
  400. for (int i = 1; i < NumRows * NumCols; ++i)
  401. {
  402. Real absElement = std::fabs(M[i]);
  403. if (absElement > maxAbsElement)
  404. {
  405. maxAbsElement = absElement;
  406. }
  407. }
  408. return maxAbsElement;
  409. }
  410. template <int N, typename Real>
  411. Matrix<N, N, Real> Inverse(Matrix<N, N, Real> const& M, bool* reportInvertibility = nullptr)
  412. {
  413. Matrix<N, N, Real> invM;
  414. Real determinant;
  415. bool invertible = GaussianElimination<Real>()(N, &M[0], &invM[0],
  416. determinant, nullptr, nullptr, nullptr, 0, nullptr);
  417. if (reportInvertibility)
  418. {
  419. *reportInvertibility = invertible;
  420. }
  421. return invM;
  422. }
  423. template <int N, typename Real>
  424. Real Determinant(Matrix<N, N, Real> const& M)
  425. {
  426. Real determinant;
  427. GaussianElimination<Real>()(N, &M[0], nullptr, determinant, nullptr,
  428. nullptr, nullptr, 0, nullptr);
  429. return determinant;
  430. }
  431. // M^T
  432. template <int NumRows, int NumCols, typename Real>
  433. Matrix<NumCols, NumRows, Real> Transpose(Matrix<NumRows, NumCols, Real> const& M)
  434. {
  435. Matrix<NumCols, NumRows, Real> result;
  436. for (int r = 0; r < NumRows; ++r)
  437. {
  438. for (int c = 0; c < NumCols; ++c)
  439. {
  440. result(c, r) = M(r, c);
  441. }
  442. }
  443. return result;
  444. }
  445. // M*V
  446. template <int NumRows, int NumCols, typename Real>
  447. Vector<NumRows, Real> operator*(Matrix<NumRows, NumCols, Real> const& M,
  448. Vector<NumCols, Real> const& V)
  449. {
  450. Vector<NumRows, Real> result;
  451. for (int r = 0; r < NumRows; ++r)
  452. {
  453. result[r] = (Real)0;
  454. for (int c = 0; c < NumCols; ++c)
  455. {
  456. result[r] += M(r, c) * V[c];
  457. }
  458. }
  459. return result;
  460. }
  461. // V^T*M
  462. template <int NumRows, int NumCols, typename Real>
  463. Vector<NumCols, Real> operator*(Vector<NumRows, Real> const& V,
  464. Matrix<NumRows, NumCols, Real> const& M)
  465. {
  466. Vector<NumCols, Real> result;
  467. for (int c = 0; c < NumCols; ++c)
  468. {
  469. result[c] = (Real)0;
  470. for (int r = 0; r < NumRows; ++r)
  471. {
  472. result[c] += V[r] * M(r, c);
  473. }
  474. }
  475. return result;
  476. }
  477. // A*B
  478. template <int NumRows, int NumCols, int NumCommon, typename Real>
  479. Matrix<NumRows, NumCols, Real> operator*(
  480. Matrix<NumRows, NumCommon, Real> const& A,
  481. Matrix<NumCommon, NumCols, Real> const& B)
  482. {
  483. return MultiplyAB(A, B);
  484. }
  485. template <int NumRows, int NumCols, int NumCommon, typename Real>
  486. Matrix<NumRows, NumCols, Real> MultiplyAB(
  487. Matrix<NumRows, NumCommon, Real> const& A,
  488. Matrix<NumCommon, NumCols, Real> const& B)
  489. {
  490. Matrix<NumRows, NumCols, Real> result;
  491. for (int r = 0; r < NumRows; ++r)
  492. {
  493. for (int c = 0; c < NumCols; ++c)
  494. {
  495. result(r, c) = (Real)0;
  496. for (int i = 0; i < NumCommon; ++i)
  497. {
  498. result(r, c) += A(r, i) * B(i, c);
  499. }
  500. }
  501. }
  502. return result;
  503. }
  504. // A*B^T
  505. template <int NumRows, int NumCols, int NumCommon, typename Real>
  506. Matrix<NumRows, NumCols, Real> MultiplyABT(
  507. Matrix<NumRows, NumCommon, Real> const& A,
  508. Matrix<NumCols, NumCommon, Real> const& B)
  509. {
  510. Matrix<NumRows, NumCols, Real> result;
  511. for (int r = 0; r < NumRows; ++r)
  512. {
  513. for (int c = 0; c < NumCols; ++c)
  514. {
  515. result(r, c) = (Real)0;
  516. for (int i = 0; i < NumCommon; ++i)
  517. {
  518. result(r, c) += A(r, i) * B(c, i);
  519. }
  520. }
  521. }
  522. return result;
  523. }
  524. // A^T*B
  525. template <int NumRows, int NumCols, int NumCommon, typename Real>
  526. Matrix<NumRows, NumCols, Real> MultiplyATB(
  527. Matrix<NumCommon, NumRows, Real> const& A,
  528. Matrix<NumCommon, NumCols, Real> const& B)
  529. {
  530. Matrix<NumRows, NumCols, Real> result;
  531. for (int r = 0; r < NumRows; ++r)
  532. {
  533. for (int c = 0; c < NumCols; ++c)
  534. {
  535. result(r, c) = (Real)0;
  536. for (int i = 0; i < NumCommon; ++i)
  537. {
  538. result(r, c) += A(i, r) * B(i, c);
  539. }
  540. }
  541. }
  542. return result;
  543. }
  544. // A^T*B^T
  545. template <int NumRows, int NumCols, int NumCommon, typename Real>
  546. Matrix<NumRows, NumCols, Real> MultiplyATBT(
  547. Matrix<NumCommon, NumRows, Real> const& A,
  548. Matrix<NumCols, NumCommon, Real> const& B)
  549. {
  550. Matrix<NumRows, NumCols, Real> result;
  551. for (int r = 0; r < NumRows; ++r)
  552. {
  553. for (int c = 0; c < NumCols; ++c)
  554. {
  555. result(r, c) = (Real)0;
  556. for (int i = 0; i < NumCommon; ++i)
  557. {
  558. result(r, c) += A(i, r) * B(c, i);
  559. }
  560. }
  561. }
  562. return result;
  563. }
  564. // M*D, D is diagonal NumCols-by-NumCols
  565. template <int NumRows, int NumCols, typename Real>
  566. Matrix<NumRows, NumCols, Real> MultiplyMD(
  567. Matrix<NumRows, NumCols, Real> const& M,
  568. Vector<NumCols, Real> const& D)
  569. {
  570. Matrix<NumRows, NumCols, Real> result;
  571. for (int r = 0; r < NumRows; ++r)
  572. {
  573. for (int c = 0; c < NumCols; ++c)
  574. {
  575. result(r, c) = M(r, c) * D[c];
  576. }
  577. }
  578. return result;
  579. }
  580. // D*M, D is diagonal NumRows-by-NumRows
  581. template <int NumRows, int NumCols, typename Real>
  582. Matrix<NumRows, NumCols, Real> MultiplyDM(
  583. Vector<NumRows, Real> const& D,
  584. Matrix<NumRows, NumCols, Real> const& M)
  585. {
  586. Matrix<NumRows, NumCols, Real> result;
  587. for (int r = 0; r < NumRows; ++r)
  588. {
  589. for (int c = 0; c < NumCols; ++c)
  590. {
  591. result(r, c) = D[r] * M(r, c);
  592. }
  593. }
  594. return result;
  595. }
  596. // U*V^T, U is NumRows-by-1, V is Num-Cols-by-1, result is NumRows-by-NumCols.
  597. template <int NumRows, int NumCols, typename Real>
  598. Matrix<NumRows, NumCols, Real> OuterProduct(
  599. Vector<NumRows, Real> const& U, Vector<NumCols, Real> const& V)
  600. {
  601. Matrix<NumRows, NumCols, Real> result;
  602. for (int r = 0; r < NumRows; ++r)
  603. {
  604. for (int c = 0; c < NumCols; ++c)
  605. {
  606. result(r, c) = U[r] * V[c];
  607. }
  608. }
  609. return result;
  610. }
  611. // Initialization to a diagonal matrix whose diagonal entries are the
  612. // components of D.
  613. template <int N, typename Real>
  614. void MakeDiagonal(Vector<N, Real> const& D, Matrix<N, N, Real>& M)
  615. {
  616. for (int i = 0; i < N * N; ++i)
  617. {
  618. M[i] = (Real)0;
  619. }
  620. for (int i = 0; i < N; ++i)
  621. {
  622. M(i, i) = D[i];
  623. }
  624. }
  625. // Create an (N+1)-by-(N+1) matrix H by setting the upper N-by-N block to
  626. // the input N-by-N matrix and all other entries to 0 except for the last
  627. // row and last column entry which is set to 1.
  628. template <int N, typename Real>
  629. Matrix<N + 1, N + 1, Real> HLift(Matrix<N, N, Real> const& M)
  630. {
  631. Matrix<N + 1, N + 1, Real> result;
  632. result.MakeIdentity();
  633. for (int r = 0; r < N; ++r)
  634. {
  635. for (int c = 0; c < N; ++c)
  636. {
  637. result(r, c) = M(r, c);
  638. }
  639. }
  640. return result;
  641. }
  642. // Extract the upper (N-1)-by-(N-1) block of the input N-by-N matrix.
  643. template <int N, typename Real>
  644. Matrix<N - 1, N - 1, Real> HProject(Matrix<N, N, Real> const& M)
  645. {
  646. static_assert(N >= 2, "Invalid matrix dimension.");
  647. Matrix<N - 1, N - 1, Real> result;
  648. for (int r = 0; r < N - 1; ++r)
  649. {
  650. for (int c = 0; c < N - 1; ++c)
  651. {
  652. result(r, c) = M(r, c);
  653. }
  654. }
  655. return result;
  656. }
  657. }