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