fork download
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <memory>
  5. #include <string>
  6. #include <vector>
  7.  
  8. namespace h3d {
  9. template <unsigned int N> class Matrix;
  10. template <unsigned int N> class Vector;
  11. };
  12.  
  13. namespace h3d {
  14. using std::ostream;
  15. using std::string;
  16.  
  17. /**
  18. * N次元正方行列クラス。
  19. * @param N 行列の次元数。
  20. */
  21. template <unsigned int N>
  22. class Matrix {
  23. public:
  24. /** 成分(Component)の配列。N×N個。 */
  25. double c[N][N];
  26.  
  27. /** 単位行列。 */
  28. static const Matrix IDENTITY;
  29.  
  30. /**
  31. * 各成分をゼロクリアする。
  32. */
  33. void clear();
  34.  
  35. /**
  36. * 行列式(DETerminant)を計算する。
  37. * @return 計算した行列式。
  38. */
  39. double det() const;
  40.  
  41. /**
  42. * 次元を一つ拡張(EXTend)した行列を作る。
  43. * @param mat この行列から最後の行と列の成分をコピーする。
  44. * @return 拡張した行列。
  45. */
  46. Matrix<N + 1> ext(const Matrix<N + 1>& mat = Matrix<N + 1>::IDENTITY) const;
  47.  
  48. /**
  49. * 逆行列(INVerse matrix)を計算する。
  50. * @return 計算した逆行列。
  51. * @throw string 行列が正則ではない場合、メッセージをスローする。
  52. */
  53. Matrix inv() const throw(string);
  54.  
  55. /**
  56. * 二つの行列が等しくないかどうかを判定する。
  57. * @param rhs 右側の行列。
  58. * @return 等しくないならtrue, 等しいならfalse。
  59. */
  60. bool operator !=(const Matrix& rhs) const;
  61.  
  62. /**
  63. * 行列で乗算する。
  64. * @param rhs 乗数となる右側の行列。
  65. * @return 乗算した行列。
  66. */
  67. Matrix operator *(const Matrix& rhs) const;
  68.  
  69. /**
  70. * ベクトルとの積を計算する。
  71. * @param rhs 乗数となる右側のベクトル。
  72. * @return 計算したベクトル。
  73. */
  74. Vector<N> operator *(const Vector<N>& rhs) const;
  75.  
  76. /**
  77. * スカラー値で乗算する。
  78. * @param rhs 乗数となる右側のスカラー値。
  79. * @return 乗算した行列。
  80. */
  81. Matrix operator *(const double& rhs) const;
  82.  
  83. /**
  84. * 行列で乗算して、代入する。
  85. * @param rhs 乗数となる右側の行列。
  86. * @return 乗算して、代入した行列。
  87. */
  88. Matrix operator *=(const Matrix& rhs);
  89.  
  90. /**
  91. * スカラー値で乗算して、代入する。
  92. * @param rhs 乗数となる右側のスカラー値。
  93. * @return 乗算して、代入した行列。
  94. */
  95. Matrix operator *=(const double& rhs);
  96.  
  97. /**
  98. * 行列を加算する。
  99. * @param rhs 加数となる右側の行列。
  100. * @return 加算した行列。
  101. */
  102. Matrix operator +(const Matrix& rhs) const;
  103.  
  104. /**
  105. * 行列を加算して、代入する。
  106. * @param rhs 加数となる右側の行列。
  107. * @return 加算して、代入した行列。
  108. */
  109. Matrix operator +=(const Matrix& rhs);
  110.  
  111. /**
  112. * すべての成分の符号を反転する。
  113. * @return 符号を反転した行列。
  114. */
  115. Matrix operator -() const;
  116.  
  117. /**
  118. * 行列を減算する。
  119. * @param rhs 減数となる右側の行列。
  120. * @return 減算した行列。
  121. */
  122. Matrix operator -(const Matrix& rhs) const;
  123.  
  124. /**
  125. * 行列を減算して、代入する。
  126. * @param rhs 減数となる右側の行列。
  127. * @return 減算して、代入した行列。
  128. */
  129. Matrix operator -=(const Matrix& rhs);
  130.  
  131. /**
  132. * スカラー値で除算する。
  133. * @param rhs 除数となる右側のスカラー値。
  134. * @return 除算した行列。
  135. */
  136. Matrix operator /(const double& rhs) const;
  137.  
  138. /**
  139. * スカラー値で除算して、代入する。
  140. * @param rhs 除数となる右側のスカラー値。
  141. * @return 除算して、代入した行列。
  142. */
  143. Matrix operator /=(const double& rhs);
  144.  
  145. /**
  146. * 二つの行列が等しいかどうかを判定する。
  147. * @param rhs 右側の行列。
  148. * @return 等しいならtrue, 等しくないならfalse。
  149. */
  150. bool operator ==(const Matrix& rhs) const;
  151.  
  152. /**
  153. * 次元を一つ縮小(SHRink)する。
  154. * @return 縮小した行列。
  155. */
  156. Matrix<N - 1> shr() const;
  157.  
  158. /**
  159. * 行と列を取り除いて、小行列(SUBmatrix)を作る。
  160. * @param row 取り除く行。
  161. * @param col 取り除く列。
  162. * @return 作った行列。
  163. */
  164. Matrix<N - 1> sub(const unsigned int& row, const unsigned int& col) const;
  165. };
  166.  
  167. template <>
  168. const Matrix<2> Matrix<2>::IDENTITY{
  169. 1.0, 0.0,
  170. 0.0, 1.0,
  171. };
  172.  
  173. template <>
  174. const Matrix<3> Matrix<3>::IDENTITY{
  175. 1.0, 0.0, 0.0,
  176. 0.0, 1.0, 0.0,
  177. 0.0, 0.0, 1.0,
  178. };
  179.  
  180. template <>
  181. const Matrix<4> Matrix<4>::IDENTITY{
  182. 1.0, 0.0, 0.0, 0.0,
  183. 0.0, 1.0, 0.0, 0.0,
  184. 0.0, 0.0, 1.0, 0.0,
  185. 0.0, 0.0, 0.0, 1.0,
  186. };
  187.  
  188. /**
  189. * 行列を出力する。
  190. * @param out 出力先となるストリーム。
  191. * @param mat 出力する行列。
  192. * @return 出力したストリーム。
  193. */
  194. template <unsigned int N> ostream& operator <<(ostream& out, const Matrix<N>& mat);
  195. };
  196.  
  197. namespace h3d {
  198. using std::copy;
  199. using std::ostream;
  200.  
  201. /**
  202. * N次元ベクトルクラス。
  203. * @param N ベクトルの次元数。
  204. */
  205. template <unsigned int N>
  206. class Vector {
  207. public:
  208. /** 成分(Component)の配列。N個。 */
  209. double c[N];
  210.  
  211. /**
  212. * 各成分をゼロクリアする。
  213. */
  214. void clear();
  215.  
  216. /**
  217. * 次元を一つ拡張(EXTend)する。
  218. * @param c 追加する成分。
  219. * @return 拡張したベクトル。
  220. */
  221. Vector<N + 1> ext(const double& c = 1.0) const;
  222.  
  223. /**
  224. * 内積(INner PROduct)を計算する。
  225. * @param rhs 右側のベクトル。
  226. * @return 計算した内積。
  227. */
  228. double inpro(const Vector& rhs) const;
  229.  
  230. /**
  231. * 二つのベクトルが等しくないかどうかを判定する。
  232. * @param rhs 右側のベクトル。
  233. * @return 等しくないならtrue, 等しいならfalse。
  234. */
  235. bool operator !=(const Vector& rhs) const;
  236.  
  237. /**
  238. * スカラー値で乗算する。
  239. * @param rhs 乗数となる右側のスカラー値。
  240. * @return 乗算したベクトル。
  241. */
  242. Vector operator *(const double& rhs) const;
  243.  
  244. /**
  245. * スカラー値で乗算して、代入する。
  246. * @param rhs 乗数となる右側のスカラー値。
  247. * @return 乗算して、代入したベクトル。
  248. */
  249. Vector& operator *=(const double& rhs);
  250.  
  251. /**
  252. * ベクトルを加算する。
  253. * @param rhs 加数となる右側のベクトル。
  254. * @return 加算したベクトル。
  255. */
  256. Vector operator +(const Vector& rhs) const;
  257.  
  258. /**
  259. * ベクトルを加算して、代入する。
  260. * @param rhs 加数となる右側のベクトル。
  261. * @return 加算して、代入したベクトル。
  262. */
  263. Vector& operator +=(const Vector& rhs);
  264.  
  265. /**
  266. * 各成分の符号を反転する。
  267. * @return 符号を反転したベクトル。
  268. */
  269. Vector operator -() const;
  270.  
  271. /**
  272. * ベクトルを減算する。
  273. * @param rhs 減数となる右側のベクトル。
  274. * @return 減算したベクトル。
  275. */
  276. Vector operator -(const Vector& rhs) const;
  277.  
  278. /**
  279. * ベクトルを減算して、代入する。
  280. * @param rhs 減数となる右側のベクトル。
  281. * @return 減算して、代入したベクトル。
  282. */
  283. Vector& operator -=(const Vector& rhs);
  284.  
  285. /**
  286. * スカラー値で除算する。
  287. * @param rhs 除数となる右側のスカラー値。
  288. * @return 除算したベクトル。
  289. */
  290. Vector operator /(const double& rhs) const;
  291.  
  292. /**
  293. * スカラー値で除算して、代入する。
  294. * @param rhs 除数となる右側のスカラー値。
  295. * @return 除算して、代入したベクトル。
  296. */
  297. Vector& operator /=(const double& rhs);
  298.  
  299. /**
  300. * 二つのベクトルが等しいかどうかを判定する。
  301. * @param rhs 右側のベクトル
  302. * @return 等しいならtrue, 等しくないならfalse。
  303. */
  304. bool operator ==(const Vector& rhs) const;
  305.  
  306. /**
  307. * 基底を直交化(ORTHOgonalize)する。
  308. * @param bases 直交化する基底。
  309. */
  310. static void ortho(Vector<N>* bases);
  311.  
  312. /**
  313. * 3次元ベクトルの外積(OUTer PROduct)を計算する。
  314. * @param rhs 右側のベクトル。
  315. * @return 計算した外積。
  316. */
  317. Vector outpro(const Vector& rhs) const;
  318.  
  319. /**
  320. * 別のベクトルに対する垂直成分(PERPendicularity)を計算する。
  321. * @param vec このベクトルに対する垂直成分を計算する。
  322. * @return 計算した垂直成分。
  323. */
  324. Vector perp(const Vector& vec) const;
  325.  
  326. /**
  327. * 別のベクトルに射影(PRoJect)する。
  328. * @param vec このベクトル上に射影する。
  329. * @return 射影したベクトル。
  330. */
  331. Vector prj(const Vector& vec) const;
  332.  
  333. /**
  334. * 次元を一つ縮小(SHRink)する。
  335. * @return 縮小したベクトル。
  336. */
  337. Vector<N - 1> shr() const;
  338. };
  339.  
  340. /**
  341. * ベクトルを出力する。
  342. * @param out 出力先となるストリーム。
  343. * @param vec 出力するベクトル。
  344. * @return 出力したストリーム。
  345. */
  346. template <unsigned int N> ostream& operator <<(ostream& out, const Vector<N>& vec);
  347. };
  348.  
  349. namespace h3d {
  350. /**
  351. * 二つの数が近いかどうかを判定する。
  352. * @param x 一つ目の数。
  353. * @param y 二つ目の数。
  354. * @return 近いならtrue, 遠いならfalse。
  355. */
  356. inline bool near(const double& x, const double& y);
  357. };
  358.  
  359. namespace h3d {
  360. using std::cout;
  361. using std::endl;
  362. using std::string;
  363.  
  364. #define ASSERT(pred) assert(#pred, (pred));
  365.  
  366. #define PRINT(val) cout << #val << "=" << (val) << endl;
  367.  
  368. /**
  369. * アサーションを実行する。
  370. * 成功なら標準出力に結果を出力する。
  371. * @param pred_str 判定する式を表した文字列。
  372. * @param pred_res 判定結果。trueなら成功,falseなら失敗と判定する。
  373. * @throw string 失敗ならメッセージをスローする。
  374. */
  375. inline void assert(const string& pred_str, const bool& pred_res) throw(string);
  376. };
  377.  
  378. namespace h3d {
  379. class Test { public: virtual void run() const = 0; };
  380. };
  381.  
  382. namespace h3d {
  383. using std::shared_ptr;
  384. using std::vector;
  385.  
  386. class TestSet {
  387. public:
  388. TestSet();
  389. void run() const;
  390. protected:
  391. vector<shared_ptr<Test>> tests;
  392. };
  393. };
  394.  
  395. namespace h3d {
  396. class Test1 : public Test {
  397. public:
  398. virtual void run() const override;
  399. };
  400. };
  401.  
  402. namespace h3d {
  403. class Test2 : public Test {
  404. public:
  405. virtual void run() const override;
  406. };
  407. };
  408.  
  409. ////////////////////////////////////////////////////////////////////////////////
  410.  
  411. namespace h3d {
  412. template <unsigned int N>
  413. void Matrix<N>::clear() {
  414. // 各成分をゼロクリアする。
  415. for (auto row = 0; row < N; row++) {
  416. for (auto col = 0; col < N; col++)
  417. this->c[row][col] = 0.0;
  418. }
  419. }
  420.  
  421. template <unsigned int N>
  422. double Matrix<N>::det() const {
  423. double res = 0.0;
  424. // 1行目の各成分ごとに反復する。
  425. for (auto col = 0; col < N; col++) {
  426. // 成分に、それと対応する小行列式を乗算する。
  427. double cofac = c[0][col] * sub(0, col).det();
  428. // (-1)^col
  429. if ((col & 0x1) == 1) cofac = -cofac;
  430. // 結果に余因子を加算する。
  431. res += cofac;
  432. }
  433. return res;
  434. }
  435.  
  436. template <unsigned int N>
  437. Matrix<N + 1> Matrix<N>::ext(const Matrix<N + 1>& mat) const {
  438. Matrix<N + 1> res;
  439. // 一つ大きい次元の各成分ごとに反復する。
  440. for (auto row = 0; row < N + 1; row++) {
  441. for (auto col = 0; col < N + 1; col++) {
  442. // 行と列がN以内ならこの行列, それ以外なら引数の行列から成分をコピーする。
  443. if (row < N && col < N) res.c[row][col] = this->c[row][col];
  444. else res.c[row][col] = mat.c[row][col];
  445. }
  446. }
  447. return res;
  448. }
  449.  
  450. template <unsigned int N>
  451. Matrix<N> Matrix<N>::inv() const throw(string) {
  452. // まず行列式を計算し、正則であることを確かめる。
  453. double dett = det();
  454. if (near(dett, 0.0)) throw "行列が正則ではない。";
  455. // 行列式の逆数を計算しておく。
  456. double inv_det = 1.0 / dett;
  457. Matrix<N> res;
  458. // 各成分ごとに反復する。
  459. for (auto row = 0; row < N; row++) {
  460. for (auto col = 0; col < N; col++) {
  461. // 行列式の逆数に、対角の小行列式を乗算する。
  462. res.c[row][col] = inv_det * sub(col, row).det();
  463. // (-1)^(row + col)
  464. if (((row + col) & 0x1) == 1)
  465. res.c[row][col] = -res.c[row][col];
  466. }
  467. }
  468. return res;
  469. }
  470.  
  471. template <>
  472. double Matrix<2>::det() const {
  473. return this->c[0][0] * this->c[1][1] - this->c[0][1] * this->c[1][0];
  474. }
  475.  
  476. template <unsigned int N>
  477. bool Matrix<N>::operator !=(const Matrix& rhs) const {
  478. return !operator ==(rhs);
  479. }
  480.  
  481. template <unsigned int N>
  482. Matrix<N> Matrix<N>::operator *(const Matrix& rhs) const {
  483. Matrix<N> res;
  484. // 各成分ごとに反復する。
  485. for (auto row = 0; row < N; row++) {
  486. for (auto col = 0; col < N; col++) {
  487. res.c[row][col] = 0.0;
  488. // 左側は対応する行, 右側は対応する列を反復して、乗算する。
  489. for (auto i = 0; i < N; i++)
  490. res.c[row][col] += this->c[row][i] * rhs.c[i][col];
  491. }
  492. }
  493. return res;
  494. }
  495.  
  496. template <unsigned int N>
  497. Vector<N> Matrix<N>::operator *(const Vector<N>& rhs) const {
  498. Vector<N> res;
  499. // ベクトルの各成分ごとに反復する。
  500. for (auto i = 0; i < N; i++) {
  501. res.c[i] = 0.0;
  502. // 左側の行列は対応する行を走査して、乗算する。
  503. for (auto j = 0; j < N; j++)
  504. res.c[i] += this->c[i][j] * rhs.c[j];
  505. }
  506. return res;
  507. }
  508.  
  509. template <unsigned int N>
  510. Matrix<N> Matrix<N>::operator *(const double& rhs) const {
  511. Matrix<N> res;
  512. // 各成分にスカラー値を乗算する。
  513. for (auto row = 0; row < N; row++) {
  514. for (auto col = 0; col < N; col++)
  515. res.c[row][col] = this->c[row][col] * rhs;
  516. }
  517. return res;
  518. }
  519.  
  520. template <unsigned int N>
  521. Matrix<N> Matrix<N>::operator *=(const Matrix& rhs) {
  522. return *this = operator *(rhs);
  523. }
  524.  
  525. template <unsigned int N>
  526. Matrix<N> Matrix<N>::operator *=(const double& rhs) {
  527. return *this = operator *(rhs);
  528. }
  529.  
  530. template <unsigned int N>
  531. Matrix<N> Matrix<N>::operator +(const Matrix& rhs) const {
  532. Matrix<N> res;
  533. // 対応する成分同士で加算する。
  534. for (auto row = 0; row < N; row++) {
  535. for (auto col = 0; col < N; col++)
  536. res.c[row][col] = this->c[row][col] + rhs.c[row][col];
  537. }
  538. return res;
  539. }
  540.  
  541. template <unsigned int N>
  542. Matrix<N> Matrix<N>::operator +=(const Matrix& rhs) {
  543. return *this = operator +(rhs);
  544. }
  545.  
  546. template <unsigned int N>
  547. Matrix<N> Matrix<N>::operator -() const {
  548. Matrix<N> res;
  549. // 各成分の符号を反転する。
  550. for (auto row = 0; row < N; row++) {
  551. for (auto col = 0; col < N; col++)
  552. res.c[row][col] = -this->c[row][col];
  553. }
  554. return res;
  555. }
  556.  
  557. template <unsigned int N>
  558. Matrix<N> Matrix<N>::operator -(const Matrix& rhs) const {
  559. return operator +(-rhs);
  560. }
  561.  
  562. template <unsigned int N>
  563. Matrix<N> Matrix<N>::operator -=(const Matrix& rhs) {
  564. return *this = operator -(rhs);
  565. }
  566.  
  567. template <unsigned int N>
  568. Matrix<N> Matrix<N>::operator /(const double& rhs) const {
  569. return operator *(1.0 / rhs);
  570. }
  571.  
  572. template <unsigned int N>
  573. Matrix<N> Matrix<N>::operator /=(const double& rhs) {
  574. return *this = operator /(rhs);
  575. }
  576.  
  577. template <unsigned int N>
  578. bool Matrix<N>::operator ==(const Matrix& rhs) const {
  579. bool res = true;
  580. if (&rhs != this) {
  581. // 各成分ごとに反復する。
  582. for (auto row = 0; row < N; row++) {
  583. for (auto col = 0; col < N; col++) {
  584. // 対応する成分同士が近ければ等しいと判定する。
  585. if (!near(this->c[row][col], rhs.c[row][col])) {
  586. res = false;
  587. break;
  588. }
  589. }
  590. if (!res) break;
  591. }
  592. }
  593. return res;
  594. }
  595.  
  596. template <unsigned int N>
  597. Matrix<N - 1> Matrix<N>::shr() const {
  598. Matrix<N - 1> res;
  599. // 一つ小さい次元の各成分ごとに反復する。
  600. for (auto row = 0; row < N - 1; row++) {
  601. // 対応する成分をコピーする。
  602. for (auto col = 0; col < N - 1; col++)
  603. res.c[row][col] = this->c[row][col];
  604. }
  605. return res;
  606. }
  607.  
  608. template <unsigned int N>
  609. Matrix<N - 1> Matrix<N>::sub(const unsigned int& row, const unsigned int& col) const {
  610. Matrix<N - 1> sub;
  611. auto sub_row = 0;
  612. // この行列の各成分ごとに反復する。
  613. // 取り除く行と列については処理をスキップする。
  614. for (auto sup_row = 0; sup_row < N; sup_row++) {
  615. if (sup_row == row) continue;
  616. auto sub_col = 0;
  617. for (auto sup_col = 0; sup_col < N; sup_col++) {
  618. if (sup_col == col) continue;
  619. // 対応する成分をコピーする。
  620. sub.c[sub_row][sub_col] = this->c[sup_row][sup_col];
  621. sub_col++;
  622. }
  623. sub_row++;
  624. }
  625. return sub;
  626. }
  627.  
  628. template <unsigned int N> ostream& operator <<(ostream& out, const Matrix<N>& mat) {
  629. out << "{";
  630. for (auto row = 0; row < N; row++) {
  631. out << "{";
  632. for (auto col = 0; col < N; col++) out << mat.c[row][col] << ", ";
  633. out << "}, ";
  634. }
  635. out << "}";
  636. }
  637. };
  638.  
  639. namespace h3d {
  640. using std::ostream;
  641.  
  642. template <unsigned int N>
  643. void Vector<N>::clear() {
  644. // 各成分をゼロクリアする。
  645. for (auto i = 0; i < N; i++) this->c[i] = 0.0;
  646. }
  647.  
  648. template <unsigned int N>
  649. Vector<N + 1> Vector<N>::ext(const double& c) const {
  650. Vector<N + 1> res;
  651. // このベクトルからN個の成分をコピーして、最後は引数の成分をコピーする。
  652. copy(this->c, this->c + N, res.c);
  653. res.c[N] = c;
  654. return res;
  655. }
  656.  
  657. template <unsigned int N>
  658. double Vector<N>::inpro(const Vector& rhs) const {
  659. double res = 0;
  660. // 対応する成分同士の積を求めて、合計する。
  661. for (auto i = 0; i < N; i++) res += this->c[i] * rhs.c[i];
  662. return res;
  663. }
  664.  
  665. template <unsigned int N>
  666. bool Vector<N>::operator !=(const Vector& rhs) const {
  667. return !operator ==(rhs);
  668. }
  669.  
  670. template <unsigned int N>
  671. Vector<N> Vector<N>::operator *(const double& rhs) const {
  672. Vector<N> res;
  673. // 各成分にスカラー値を乗算する。
  674. for (auto i = 0; i < N; i++) res.c[i] = this->c[i] * rhs;
  675. return res;
  676. }
  677.  
  678. template <unsigned int N>
  679. Vector<N>& Vector<N>::operator *=(const double& rhs) {
  680. return *this = operator *(rhs);
  681. }
  682.  
  683. template <unsigned int N>
  684. Vector<N> Vector<N>::operator +(const Vector& rhs) const {
  685. Vector<N> res;
  686. // 対応する成分同士で加算する。
  687. for (auto i = 0; i < N; i++) res.c[i] = this->c[i] + rhs.c[i];
  688. return res;
  689. }
  690.  
  691. template <unsigned int N>
  692. Vector<N>& Vector<N>::operator +=(const Vector& rhs) {
  693. return *this = operator +(rhs);
  694. }
  695.  
  696. template <unsigned int N>
  697. Vector<N> Vector<N>::operator -() const {
  698. Vector<N> res;
  699. // 各成分の符号を反転する。
  700. for (auto i = 0; i < N; i++) res.c[i] = -this->c[i];
  701. return res;
  702. }
  703.  
  704. template <unsigned int N>
  705. Vector<N> Vector<N>::operator -(const Vector& rhs) const {
  706. return operator +(-rhs);
  707. }
  708.  
  709. template <unsigned int N>
  710. Vector<N>& Vector<N>::operator -=(const Vector& rhs) {
  711. return *this = operator -(rhs);
  712. }
  713.  
  714. template <unsigned int N>
  715. Vector<N> Vector<N>::operator /(const double& rhs) const {
  716. return operator *(1.0 / rhs);
  717. }
  718.  
  719. template <unsigned int N>
  720. Vector<N>& Vector<N>::operator /=(const double& rhs) {
  721. return *this = operator /(rhs);
  722. }
  723.  
  724. template <unsigned int N>
  725. bool Vector<N>::operator ==(const Vector& rhs) const {
  726. bool res = true;
  727. if (&rhs != this) {
  728. // 各成分ごとに反復する。
  729. for (auto i = 0; i < N; i++) {
  730. // 対応する成分同士が近ければ等しいと判定する。
  731. if (!near(this->c[i], rhs.c[i])) {
  732. res = false;
  733. break;
  734. }
  735. }
  736. }
  737. return res;
  738. }
  739.  
  740. template <unsigned int N>
  741. void Vector<N>::ortho(Vector<N>* bases) {
  742. // グラム・シュミットの直交化法。
  743. for (auto i = 2; i < N; i++) {
  744. Vector<N> sum;
  745. sum.clear();
  746. for (auto j = 0; j < i; j++) sum += bases[i].prj(bases[j]);
  747. bases[i] -= sum;
  748. }
  749. }
  750.  
  751. template <unsigned int N>
  752. Vector<N> Vector<N>::outpro(const Vector& rhs) const {
  753. // 各成分について、対応する列を除いた2×2の行列式を計算する。
  754. // P×Q = < Py・Qz - Pz・Qy, Pz・Qx - Px・Qz, Px・Qy - Py・Qx >
  755. return Vector<N>{
  756. this->c[1] * rhs.c[2] - this->c[2] * rhs.c[1],
  757. this->c[2] * rhs.c[0] - this->c[0] * rhs.c[2],
  758. this->c[0] * rhs.c[1] - this->c[1] * rhs.c[0],
  759. };
  760. }
  761.  
  762. template <unsigned int N>
  763. Vector<N> Vector<N>::perp(const Vector& vec) const {
  764. // 射影したベクトルを引けば、垂直成分が残る。
  765. return *this - prj(vec);
  766. }
  767.  
  768. template <unsigned int N>
  769. Vector<N> Vector<N>::prj(const Vector& vec) const {
  770. // PをQ上に射影した結果は次式で与えられる。
  771. // P・Q
  772. // -----・Q
  773. // |Q|^2
  774. return vec * inpro(vec) / vec.inpro(vec);
  775. }
  776.  
  777. template <unsigned int N>
  778. Vector<N - 1> Vector<N>::shr() const {
  779. Vector<N - 1> res;
  780. copy(this->c, this->c + N - 1, res.c);
  781. return res;
  782. }
  783.  
  784. template <unsigned int N> ostream& operator <<(ostream& out, const Vector<N>& vec) {
  785. out << "{";
  786. for (auto c : vec.c) out << c << ", ";
  787. out << "}";
  788. }
  789. };
  790.  
  791. namespace h3d {
  792. inline bool near(const double& x, const double& y) {
  793. static const double THRESHOLD = 0.0000001;
  794. double dif = x - y;
  795. return dif > -THRESHOLD && dif < THRESHOLD;
  796. }
  797. };
  798.  
  799. namespace h3d {
  800. using std::cout;
  801. using std::endl;
  802. using std::string;
  803.  
  804. inline void assert(const string& pred_str, const bool& pred_res) throw(string) {
  805. if (pred_res) cout << "アサート成功: " << pred_str << endl;
  806. else throw "アサート失敗: " + pred_str;
  807. }
  808. };
  809.  
  810. namespace h3d {
  811. using std::shared_ptr;
  812.  
  813. TestSet::TestSet() {
  814. this->tests.push_back(shared_ptr<Test>(new Test1));
  815. this->tests.push_back(shared_ptr<Test>(new Test2));
  816. }
  817.  
  818. void TestSet::run() const { for (auto iter : this->tests) iter->run(); }
  819. };
  820.  
  821. namespace h3d {
  822. using std::sqrt;
  823.  
  824. void Test1::run() const {
  825. Vector<3> p{2.0, 2.0, 1.0}, q{1.0, -2.0, 0.0};
  826. ASSERT(near(p.c[0], 2.0))
  827. ASSERT(near(p.c[1], 2.0))
  828. ASSERT(near(p.c[2], 1.0))
  829. ASSERT(near(q.c[0], 1.0))
  830. ASSERT(near(q.c[1], -2.0))
  831. ASSERT(near(q.c[2], 0.0))
  832.  
  833. ASSERT(p.ext() == (Vector<4>{2.0, 2.0, 1.0, 1.0}))
  834. ASSERT(p.ext(0.0) == (Vector<4>{2.0, 2.0, 1.0, 0.0}))
  835. ASSERT(p.shr() == (Vector<2>{2.0, 2.0}))
  836.  
  837. ASSERT(p == (Vector<3>{2.0, 2.0, 1.0}))
  838. ASSERT(q == (Vector<3>{1.0, -2.0, 0.0}))
  839. ASSERT(p != (Vector<3>{1.0, -2.0, 0.0}))
  840. ASSERT(q != (Vector<3>{2.0, 2.0, 1.0}))
  841. ASSERT(-p == (Vector<3>{-2.0, -2.0, -1.0}))
  842. ASSERT(-q == (Vector<3>{-1.0, 2.0, 0.0}))
  843. ASSERT(p * 2.0 == (Vector<3>{4.0, 4.0, 2.0}))
  844. ASSERT(q * -3.0 == (Vector<3>{-3.0, 6.0, 0.0}))
  845. ASSERT(p / 2.0 == (Vector<3>{1.0, 1.0, 0.5}))
  846. ASSERT(q / -3.0 == (Vector<3>{1.0 / -3.0, -2.0 / -3.0, 0.0}))
  847.  
  848. ASSERT(p + q == (Vector<3>{3.0, 0.0, 1.0}))
  849. ASSERT(q + p == (Vector<3>{3.0, 0.0, 1.0}))
  850. ASSERT(p - q == (Vector<3>{1.0, 4.0, 1.0}))
  851. ASSERT(q - p == (Vector<3>{-1.0, -4.0, -1.0}))
  852.  
  853. Vector<3> r;
  854. r = p;
  855. ASSERT(r == (Vector<3>{2.0, 2.0, 1.0}))
  856. ASSERT((r *= 3.0) == (Vector<3>{6.0, 6.0, 3.0}))
  857. ASSERT((r /= -2.0) == (Vector<3>{-3.0, -3.0, -1.5}))
  858. ASSERT((r += (Vector<3>{5.0, -1.0, 0.0})) == (Vector<3>{2.0, -4.0, -1.5}))
  859. ASSERT((r -= (Vector<3>{0.0, -2.0, 4.0})) == (Vector<3>{2.0, -2.0, -5.5}))
  860. r.clear();
  861. ASSERT(near(r.c[0], 0.0))
  862. ASSERT(near(r.c[1], 0.0))
  863. ASSERT(near(r.c[2], 0.0))
  864.  
  865. ASSERT(near(p.inpro(q), -2.0))
  866. ASSERT(p.outpro(q) == (Vector<3>{2.0, 1.0, -6.0}))
  867. ASSERT(p.prj(q) == (Vector<3>{-0.4, 0.8, 0.0}))
  868. ASSERT(q.prj(p) == (Vector<3>{-4.0 / 9.0, -4.0 / 9.0, -2.0 / 9.0}))
  869. ASSERT(p.perp(q) == (Vector<3>{2.4, 1.2, 1.0}))
  870. ASSERT(q.perp(p) == (Vector<3>{1.0 + 4.0 / 9.0, -2.0 + 4.0 / 9.0, 2.0 / 9.0}))
  871.  
  872. Vector<3> e[3] = {
  873. {sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, 0.0},
  874. {-1.0, 1.0, -1.0},
  875. {0.0, -2.0, -2.0},
  876. };
  877. Vector<3>::ortho(e);
  878. ASSERT(e[0] == (Vector<3>{sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, 0.0}))
  879. ASSERT(e[1] == (Vector<3>{-1.0, 1.0, -1.0}))
  880. ASSERT(e[2] == (Vector<3>{1.0, -1.0, -2.0}))
  881. }
  882. };
  883.  
  884. namespace h3d {
  885. using std::cos;
  886. using std::sin;
  887. using std::sqrt;
  888.  
  889. void Test2::run() const {
  890. ASSERT(near(Matrix<2>::IDENTITY.c[0][0], 1.0))
  891. ASSERT(near(Matrix<2>::IDENTITY.c[0][1], 0.0))
  892. ASSERT(near(Matrix<2>::IDENTITY.c[1][0], 0.0))
  893. ASSERT(near(Matrix<2>::IDENTITY.c[1][1], 1.0))
  894. ASSERT(near(Matrix<3>::IDENTITY.c[0][0], 1.0))
  895. ASSERT(near(Matrix<3>::IDENTITY.c[0][1], 0.0))
  896. ASSERT(near(Matrix<3>::IDENTITY.c[0][2], 0.0))
  897. ASSERT(near(Matrix<3>::IDENTITY.c[1][0], 0.0))
  898. ASSERT(near(Matrix<3>::IDENTITY.c[1][1], 1.0))
  899. ASSERT(near(Matrix<3>::IDENTITY.c[1][2], 0.0))
  900. ASSERT(near(Matrix<3>::IDENTITY.c[2][0], 0.0))
  901. ASSERT(near(Matrix<3>::IDENTITY.c[2][1], 0.0))
  902. ASSERT(near(Matrix<3>::IDENTITY.c[2][2], 1.0))
  903. ASSERT(near(Matrix<4>::IDENTITY.c[0][0], 1.0))
  904. ASSERT(near(Matrix<4>::IDENTITY.c[0][1], 0.0))
  905. ASSERT(near(Matrix<4>::IDENTITY.c[0][2], 0.0))
  906. ASSERT(near(Matrix<4>::IDENTITY.c[0][3], 0.0))
  907. ASSERT(near(Matrix<4>::IDENTITY.c[1][0], 0.0))
  908. ASSERT(near(Matrix<4>::IDENTITY.c[1][1], 1.0))
  909. ASSERT(near(Matrix<4>::IDENTITY.c[1][2], 0.0))
  910. ASSERT(near(Matrix<4>::IDENTITY.c[1][3], 0.0))
  911. ASSERT(near(Matrix<4>::IDENTITY.c[2][0], 0.0))
  912. ASSERT(near(Matrix<4>::IDENTITY.c[2][1], 0.0))
  913. ASSERT(near(Matrix<4>::IDENTITY.c[2][2], 1.0))
  914. ASSERT(near(Matrix<4>::IDENTITY.c[2][3], 0.0))
  915. ASSERT(near(Matrix<4>::IDENTITY.c[3][0], 0.0))
  916. ASSERT(near(Matrix<4>::IDENTITY.c[3][1], 0.0))
  917. ASSERT(near(Matrix<4>::IDENTITY.c[3][2], 0.0))
  918. ASSERT(near(Matrix<4>::IDENTITY.c[3][3], 1.0))
  919.  
  920. Matrix<2> f{
  921. 1.0, -2.0,
  922. -3.0, 4.0,
  923. }, g{
  924. -9.0, 8.0,
  925. 7.0, -6.0,
  926. };
  927.  
  928. ASSERT(near(f.c[0][0], 1.0))
  929. ASSERT(near(f.c[0][1], -2.0))
  930. ASSERT(near(f.c[1][0], -3.0))
  931. ASSERT(near(f.c[1][1], 4.0))
  932. ASSERT(near(g.c[0][0], -9.0))
  933. ASSERT(near(g.c[0][1], 8.0))
  934. ASSERT(near(g.c[1][0], 7.0))
  935. ASSERT(near(g.c[1][1], -6.0))
  936.  
  937. ASSERT(f.ext() == (Matrix<3>{
  938. 1.0, -2.0, 0.0,
  939. -3.0, 4.0, 0.0,
  940. 0.0, 0.0, 1.0,
  941. }))
  942. ASSERT(f.ext((Matrix<3>{
  943. 3.0, -8.0, 5.0,
  944. -2.0, 7.0, 4.0,
  945. 1.0, -5.0, 0.0,
  946. })) == (Matrix<3>{
  947. 1.0, -2.0, 5.0,
  948. -3.0, 4.0, 4.0,
  949. 1.0, -5.0, 0.0,
  950. }))
  951. ASSERT(f.shr() == (Matrix<1>{
  952. 1.0,
  953. }))
  954.  
  955. ASSERT(f == (Matrix<2>{
  956. 1.0, -2.0,
  957. -3.0, 4.0,
  958. }))
  959. ASSERT(g == (Matrix<2>{
  960. -9.0, 8.0,
  961. 7.0, -6.0,
  962. }))
  963. ASSERT(f != (Matrix<2>{
  964. -9.0, 8.0,
  965. 7.0, -6.0,
  966. }))
  967. ASSERT(g != (Matrix<2>{
  968. 1.0, -2.0,
  969. -3.0, 4.0,
  970. }))
  971.  
  972. ASSERT(-f == (Matrix<2>{
  973. -1.0, 2.0,
  974. 3.0, -4.0,
  975. }))
  976. ASSERT(-g == (Matrix<2>{
  977. 9.0, -8.0,
  978. -7.0, 6.0,
  979. }))
  980. ASSERT(f + g == (Matrix<2>{
  981. -8.0, 6.0,
  982. 4.0, -2.0,
  983. }))
  984. ASSERT(f - g == (Matrix<2>{
  985. 10.0, -10.0,
  986. -10.0, 10.0,
  987. }))
  988. ASSERT(f * g == (Matrix<2>{
  989. -23.0, 20.0,
  990. 55.0, -48.0,
  991. }))
  992. ASSERT(g * f == (Matrix<2>{
  993. -33.0, 50.0,
  994. 25.0, -38.0,
  995. }))
  996. ASSERT(f * Matrix<2>::IDENTITY == (Matrix<2>{
  997. 1.0, -2.0,
  998. -3.0, 4.0,
  999. }))
  1000. ASSERT(Matrix<2>::IDENTITY * g == (Matrix<2>{
  1001. -9.0, 8.0,
  1002. 7.0, -6.0,
  1003. }))
  1004. ASSERT(f * 3.0 == (Matrix<2>{
  1005. 3.0, -6.0,
  1006. -9.0, 12.0,
  1007. }))
  1008. ASSERT(g / -2.0 == (Matrix<2>{
  1009. 4.5, -4.0,
  1010. -3.5, 3.0,
  1011. }))
  1012.  
  1013. Matrix<2> h;
  1014. h = f;
  1015. ASSERT(h == (Matrix<2>{
  1016. 1.0, -2.0,
  1017. -3.0, 4.0,
  1018. }))
  1019. ASSERT((h += (Matrix<2>{
  1020. 0.1, -0.2,
  1021. -0.3, 0.4,
  1022. })) == (Matrix<2>{
  1023. 1.1, -2.2,
  1024. -3.3, 4.4,
  1025. }))
  1026. ASSERT((h -= (Matrix<2>{
  1027. -0.9, 0.8,
  1028. 0.7, -0.6,
  1029. })) == (Matrix<2>{
  1030. 2.0, -3.0,
  1031. -4.0, 5.0,
  1032. }))
  1033. ASSERT((h *= (Matrix<2>{
  1034. -4.0, 3.0,
  1035. -2.0, 1.0,
  1036. })) == (Matrix<2>{
  1037. -2.0, 3.0,
  1038. 6.0, -7.0,
  1039. }))
  1040. ASSERT((h *= 3.0) == (Matrix<2>{
  1041. -6.0, 9.0,
  1042. 18.0, -21.0,
  1043. }))
  1044. ASSERT((h /= -2.0) == (Matrix<2>{
  1045. 3.0, -4.5,
  1046. -9.0, 10.5,
  1047. }))
  1048. h.clear();
  1049. ASSERT(near(h.c[0][0], 0.0))
  1050. ASSERT(near(h.c[0][1], 0.0))
  1051. ASSERT(near(h.c[1][0], 0.0))
  1052. ASSERT(near(h.c[1][1], 0.0))
  1053.  
  1054. ASSERT(near((Matrix<2>{
  1055. 2.0, 7.0,
  1056. -3.0, 0.5,
  1057. }).det(), 22.0))
  1058. ASSERT(near((Matrix<3>{
  1059. 0.0, 0.0, 1.0,
  1060. 0.0, 1.0, 0.0,
  1061. 1.0, 0.0, 0.0,
  1062. }).det(), -1.0))
  1063. ASSERT(near((Matrix<3>{
  1064. 0.5, sqrt(3.0) / 2.0, 0.0,
  1065. -sqrt(3.0) / 2.0, 0.5, 0.0,
  1066. 0.0, 0.0, 1.0,
  1067. }).det(), 1.0))
  1068. ASSERT(near((Matrix<3>{
  1069. 5, 7, 1,
  1070. 17, 2, 64,
  1071. 10, 14, 2,
  1072. }).det(), 0.0))
  1073.  
  1074. ASSERT((Matrix<3>{
  1075. 2.0, 0.0, 0.0,
  1076. 0.0, 3.0, 0.0,
  1077. 0.0, 0.0, 4.0,
  1078. }).inv() == (Matrix<3>{
  1079. 12.0, 0.0, 0.0,
  1080. 0.0, 8.0, 0.0,
  1081. 0.0, 0.0, 6.0,
  1082. }) / 24.0)
  1083. ASSERT((Matrix<3>{
  1084. 2.0, 0.0, 0.0,
  1085. 0.0, 3.0, 0.0,
  1086. 0.0, 0.0, 4.0,
  1087. }) * ((Matrix<3>{
  1088. 12.0, 0.0, 0.0,
  1089. 0.0, 8.0, 0.0,
  1090. 0.0, 0.0, 6.0,
  1091. }) / 24.0) == Matrix<3>::IDENTITY)
  1092. ASSERT((Matrix<3>{
  1093. 1.0, 0.0, 0.0,
  1094. 0.0, 2.0, 2.0,
  1095. 3.0, 0.0, 8.0,
  1096. }).inv() == (Matrix<3>{
  1097. 16.0, 0.0, 0.0,
  1098. 6.0, 8.0, -2.0,
  1099. -6.0, 0.0, 2.0,
  1100. }) / 16.0)
  1101. ASSERT((Matrix<3>{
  1102. 1.0, 0.0, 0.0,
  1103. 0.0, 2.0, 2.0,
  1104. 3.0, 0.0, 8.0,
  1105. }) * ((Matrix<3>{
  1106. 16.0, 0.0, 0.0,
  1107. 6.0, 8.0, -2.0,
  1108. -6.0, 0.0, 2.0,
  1109. }) / 16.0) == Matrix<3>::IDENTITY)
  1110. double theta = 60.0;
  1111. double theta_rad = M_PI * theta / 180.0;
  1112. double coss = cos(theta_rad);
  1113. double sinn = sin(theta_rad);
  1114. ASSERT((Matrix<3>{
  1115. coss, 0.0, -sinn,
  1116. 0.0, 1.0, 0.0,
  1117. sinn, 0.0, coss,
  1118. }).inv() == (Matrix<3>{
  1119. coss, 0.0, sinn,
  1120. 0.0, 1.0, 0.0,
  1121. -sinn, 0.0, coss,
  1122. }))
  1123. ASSERT((Matrix<3>{
  1124. coss, 0.0, -sinn,
  1125. 0.0, 1.0, 0.0,
  1126. sinn, 0.0, coss,
  1127. }) * (Matrix<3>{
  1128. coss, 0.0, sinn,
  1129. 0.0, 1.0, 0.0,
  1130. -sinn, 0.0, coss,
  1131. }) == Matrix<3>::IDENTITY)
  1132. ASSERT((Matrix<4>{
  1133. 1.0, 0.0, 0.0, 4.0,
  1134. 0.0, 1.0, 0.0, 3.0,
  1135. 0.0, 0.0, 1.0, 7.0,
  1136. 0.0, 0.0, 0.0, 1.0,
  1137. }).inv() == (Matrix<4>{
  1138. 1.0, 0.0, 0.0, -4.0,
  1139. 0.0, 1.0, 0.0, -3.0,
  1140. 0.0, 0.0, 1.0, -7.0,
  1141. 0.0, 0.0, 0.0, 1.0,
  1142. }))
  1143. ASSERT((Matrix<4>{
  1144. 1.0, 0.0, 0.0, 4.0,
  1145. 0.0, 1.0, 0.0, 3.0,
  1146. 0.0, 0.0, 1.0, 7.0,
  1147. 0.0, 0.0, 0.0, 1.0,
  1148. }) * (Matrix<4>{
  1149. 1.0, 0.0, 0.0, -4.0,
  1150. 0.0, 1.0, 0.0, -3.0,
  1151. 0.0, 0.0, 1.0, -7.0,
  1152. 0.0, 0.0, 0.0, 1.0,
  1153. }) == Matrix<4>::IDENTITY)
  1154.  
  1155. ASSERT((Matrix<2>{
  1156. 1.0, -3.0,
  1157. -4.0, 6.0,
  1158. }) * (Vector<2>{2.0, 5.0}) == (Vector<2>{-13.0, 22.0}))
  1159. ASSERT((Matrix<2>{
  1160. 0.0, 8.0,
  1161. -9.0, 3.0,
  1162. }) * (Vector<2>{1.0, -4.0}) == (Vector<2>{-32.0, -21.0}))
  1163. }
  1164. };
  1165.  
  1166. int main() {
  1167. using std::cerr;
  1168. using std::endl;
  1169. using std::string;
  1170.  
  1171. try {
  1172. h3d::TestSet().run();
  1173. }
  1174. catch (const string& msg) {
  1175. cerr << msg << endl;
  1176. return 1;
  1177. }
  1178. return 0;
  1179. }
  1180.  
Success #stdin #stdout 0s 3532KB
stdin
Standard input is empty
stdout
アサート成功: near(p.c[0], 2.0)
アサート成功: near(p.c[1], 2.0)
アサート成功: near(p.c[2], 1.0)
アサート成功: near(q.c[0], 1.0)
アサート成功: near(q.c[1], -2.0)
アサート成功: near(q.c[2], 0.0)
アサート成功: p.ext() == (Vector<4>{2.0, 2.0, 1.0, 1.0})
アサート成功: p.ext(0.0) == (Vector<4>{2.0, 2.0, 1.0, 0.0})
アサート成功: p.shr() == (Vector<2>{2.0, 2.0})
アサート成功: p == (Vector<3>{2.0, 2.0, 1.0})
アサート成功: q == (Vector<3>{1.0, -2.0, 0.0})
アサート成功: p != (Vector<3>{1.0, -2.0, 0.0})
アサート成功: q != (Vector<3>{2.0, 2.0, 1.0})
アサート成功: -p == (Vector<3>{-2.0, -2.0, -1.0})
アサート成功: -q == (Vector<3>{-1.0, 2.0, 0.0})
アサート成功: p * 2.0 == (Vector<3>{4.0, 4.0, 2.0})
アサート成功: q * -3.0 == (Vector<3>{-3.0, 6.0, 0.0})
アサート成功: p / 2.0 == (Vector<3>{1.0, 1.0, 0.5})
アサート成功: q / -3.0 == (Vector<3>{1.0 / -3.0, -2.0 / -3.0, 0.0})
アサート成功: p + q == (Vector<3>{3.0, 0.0, 1.0})
アサート成功: q + p == (Vector<3>{3.0, 0.0, 1.0})
アサート成功: p - q == (Vector<3>{1.0, 4.0, 1.0})
アサート成功: q - p == (Vector<3>{-1.0, -4.0, -1.0})
アサート成功: r == (Vector<3>{2.0, 2.0, 1.0})
アサート成功: (r *= 3.0) == (Vector<3>{6.0, 6.0, 3.0})
アサート成功: (r /= -2.0) == (Vector<3>{-3.0, -3.0, -1.5})
アサート成功: (r += (Vector<3>{5.0, -1.0, 0.0})) == (Vector<3>{2.0, -4.0, -1.5})
アサート成功: (r -= (Vector<3>{0.0, -2.0, 4.0})) == (Vector<3>{2.0, -2.0, -5.5})
アサート成功: near(r.c[0], 0.0)
アサート成功: near(r.c[1], 0.0)
アサート成功: near(r.c[2], 0.0)
アサート成功: near(p.inpro(q), -2.0)
アサート成功: p.outpro(q) == (Vector<3>{2.0, 1.0, -6.0})
アサート成功: p.prj(q) == (Vector<3>{-0.4, 0.8, 0.0})
アサート成功: q.prj(p) == (Vector<3>{-4.0 / 9.0, -4.0 / 9.0, -2.0 / 9.0})
アサート成功: p.perp(q) == (Vector<3>{2.4, 1.2, 1.0})
アサート成功: q.perp(p) == (Vector<3>{1.0 + 4.0 / 9.0, -2.0 + 4.0 / 9.0, 2.0 / 9.0})
アサート成功: e[0] == (Vector<3>{sqrt(2.0) / 2.0, sqrt(2.0) / 2.0, 0.0})
アサート成功: e[1] == (Vector<3>{-1.0, 1.0, -1.0})
アサート成功: e[2] == (Vector<3>{1.0, -1.0, -2.0})
アサート成功: near(Matrix<2>::IDENTITY.c[0][0], 1.0)
アサート成功: near(Matrix<2>::IDENTITY.c[0][1], 0.0)
アサート成功: near(Matrix<2>::IDENTITY.c[1][0], 0.0)
アサート成功: near(Matrix<2>::IDENTITY.c[1][1], 1.0)
アサート成功: near(Matrix<3>::IDENTITY.c[0][0], 1.0)
アサート成功: near(Matrix<3>::IDENTITY.c[0][1], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[0][2], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[1][0], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[1][1], 1.0)
アサート成功: near(Matrix<3>::IDENTITY.c[1][2], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[2][0], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[2][1], 0.0)
アサート成功: near(Matrix<3>::IDENTITY.c[2][2], 1.0)
アサート成功: near(Matrix<4>::IDENTITY.c[0][0], 1.0)
アサート成功: near(Matrix<4>::IDENTITY.c[0][1], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[0][2], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[0][3], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[1][0], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[1][1], 1.0)
アサート成功: near(Matrix<4>::IDENTITY.c[1][2], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[1][3], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[2][0], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[2][1], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[2][2], 1.0)
アサート成功: near(Matrix<4>::IDENTITY.c[2][3], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[3][0], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[3][1], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[3][2], 0.0)
アサート成功: near(Matrix<4>::IDENTITY.c[3][3], 1.0)
アサート成功: near(f.c[0][0], 1.0)
アサート成功: near(f.c[0][1], -2.0)
アサート成功: near(f.c[1][0], -3.0)
アサート成功: near(f.c[1][1], 4.0)
アサート成功: near(g.c[0][0], -9.0)
アサート成功: near(g.c[0][1], 8.0)
アサート成功: near(g.c[1][0], 7.0)
アサート成功: near(g.c[1][1], -6.0)
アサート成功: f.ext() == (Matrix<3>{ 1.0, -2.0, 0.0, -3.0, 4.0, 0.0, 0.0, 0.0, 1.0, })
アサート成功: f.ext((Matrix<3>{ 3.0, -8.0, 5.0, -2.0, 7.0, 4.0, 1.0, -5.0, 0.0, })) == (Matrix<3>{ 1.0, -2.0, 5.0, -3.0, 4.0, 4.0, 1.0, -5.0, 0.0, })
アサート成功: f.shr() == (Matrix<1>{ 1.0, })
アサート成功: f == (Matrix<2>{ 1.0, -2.0, -3.0, 4.0, })
アサート成功: g == (Matrix<2>{ -9.0, 8.0, 7.0, -6.0, })
アサート成功: f != (Matrix<2>{ -9.0, 8.0, 7.0, -6.0, })
アサート成功: g != (Matrix<2>{ 1.0, -2.0, -3.0, 4.0, })
アサート成功: -f == (Matrix<2>{ -1.0, 2.0, 3.0, -4.0, })
アサート成功: -g == (Matrix<2>{ 9.0, -8.0, -7.0, 6.0, })
アサート成功: f + g == (Matrix<2>{ -8.0, 6.0, 4.0, -2.0, })
アサート成功: f - g == (Matrix<2>{ 10.0, -10.0, -10.0, 10.0, })
アサート成功: f * g == (Matrix<2>{ -23.0, 20.0, 55.0, -48.0, })
アサート成功: g * f == (Matrix<2>{ -33.0, 50.0, 25.0, -38.0, })
アサート成功: f * Matrix<2>::IDENTITY == (Matrix<2>{ 1.0, -2.0, -3.0, 4.0, })
アサート成功: Matrix<2>::IDENTITY * g == (Matrix<2>{ -9.0, 8.0, 7.0, -6.0, })
アサート成功: f * 3.0 == (Matrix<2>{ 3.0, -6.0, -9.0, 12.0, })
アサート成功: g / -2.0 == (Matrix<2>{ 4.5, -4.0, -3.5, 3.0, })
アサート成功: h == (Matrix<2>{ 1.0, -2.0, -3.0, 4.0, })
アサート成功: (h += (Matrix<2>{ 0.1, -0.2, -0.3, 0.4, })) == (Matrix<2>{ 1.1, -2.2, -3.3, 4.4, })
アサート成功: (h -= (Matrix<2>{ -0.9, 0.8, 0.7, -0.6, })) == (Matrix<2>{ 2.0, -3.0, -4.0, 5.0, })
アサート成功: (h *= (Matrix<2>{ -4.0, 3.0, -2.0, 1.0, })) == (Matrix<2>{ -2.0, 3.0, 6.0, -7.0, })
アサート成功: (h *= 3.0) == (Matrix<2>{ -6.0, 9.0, 18.0, -21.0, })
アサート成功: (h /= -2.0) == (Matrix<2>{ 3.0, -4.5, -9.0, 10.5, })
アサート成功: near(h.c[0][0], 0.0)
アサート成功: near(h.c[0][1], 0.0)
アサート成功: near(h.c[1][0], 0.0)
アサート成功: near(h.c[1][1], 0.0)
アサート成功: near((Matrix<2>{ 2.0, 7.0, -3.0, 0.5, }).det(), 22.0)
アサート成功: near((Matrix<3>{ 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, }).det(), -1.0)
アサート成功: near((Matrix<3>{ 0.5, sqrt(3.0) / 2.0, 0.0, -sqrt(3.0) / 2.0, 0.5, 0.0, 0.0, 0.0, 1.0, }).det(), 1.0)
アサート成功: near((Matrix<3>{ 5, 7, 1, 17, 2, 64, 10, 14, 2, }).det(), 0.0)
アサート成功: (Matrix<3>{ 2.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 4.0, }).inv() == (Matrix<3>{ 12.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 6.0, }) / 24.0
アサート成功: (Matrix<3>{ 2.0, 0.0, 0.0, 0.0, 3.0, 0.0, 0.0, 0.0, 4.0, }) * ((Matrix<3>{ 12.0, 0.0, 0.0, 0.0, 8.0, 0.0, 0.0, 0.0, 6.0, }) / 24.0) == Matrix<3>::IDENTITY
アサート成功: (Matrix<3>{ 1.0, 0.0, 0.0, 0.0, 2.0, 2.0, 3.0, 0.0, 8.0, }).inv() == (Matrix<3>{ 16.0, 0.0, 0.0, 6.0, 8.0, -2.0, -6.0, 0.0, 2.0, }) / 16.0
アサート成功: (Matrix<3>{ 1.0, 0.0, 0.0, 0.0, 2.0, 2.0, 3.0, 0.0, 8.0, }) * ((Matrix<3>{ 16.0, 0.0, 0.0, 6.0, 8.0, -2.0, -6.0, 0.0, 2.0, }) / 16.0) == Matrix<3>::IDENTITY
アサート成功: (Matrix<3>{ coss, 0.0, -sinn, 0.0, 1.0, 0.0, sinn, 0.0, coss, }).inv() == (Matrix<3>{ coss, 0.0, sinn, 0.0, 1.0, 0.0, -sinn, 0.0, coss, })
アサート成功: (Matrix<3>{ coss, 0.0, -sinn, 0.0, 1.0, 0.0, sinn, 0.0, coss, }) * (Matrix<3>{ coss, 0.0, sinn, 0.0, 1.0, 0.0, -sinn, 0.0, coss, }) == Matrix<3>::IDENTITY
アサート成功: (Matrix<4>{ 1.0, 0.0, 0.0, 4.0, 0.0, 1.0, 0.0, 3.0, 0.0, 0.0, 1.0, 7.0, 0.0, 0.0, 0.0, 1.0, }).inv() == (Matrix<4>{ 1.0, 0.0, 0.0, -4.0, 0.0, 1.0, 0.0, -3.0, 0.0, 0.0, 1.0, -7.0, 0.0, 0.0, 0.0, 1.0, })
アサート成功: (Matrix<4>{ 1.0, 0.0, 0.0, 4.0, 0.0, 1.0, 0.0, 3.0, 0.0, 0.0, 1.0, 7.0, 0.0, 0.0, 0.0, 1.0, }) * (Matrix<4>{ 1.0, 0.0, 0.0, -4.0, 0.0, 1.0, 0.0, -3.0, 0.0, 0.0, 1.0, -7.0, 0.0, 0.0, 0.0, 1.0, }) == Matrix<4>::IDENTITY
アサート成功: (Matrix<2>{ 1.0, -3.0, -4.0, 6.0, }) * (Vector<2>{2.0, 5.0}) == (Vector<2>{-13.0, 22.0})
アサート成功: (Matrix<2>{ 0.0, 8.0, -9.0, 3.0, }) * (Vector<2>{1.0, -4.0}) == (Vector<2>{-32.0, -21.0})