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