fork download
  1. namespace h3d {
  2. /**
  3. * N次ベクトルクラス。
  4. * @param N ベクトルの次数。
  5. */
  6. template <unsigned int N>
  7. class Vector {
  8. public:
  9. /** 成分の配列。N個。 */
  10. double f[N];
  11.  
  12. /**
  13. * 二つのベクトルの内積を計算する。
  14. * @param vec 右側のベクトル。
  15. * @return 計算した内積。
  16. */
  17. double inpro(const Vector& rhs) const;
  18.  
  19. /**
  20. * スカラー値との積を計算する。
  21. * @param sca 乗数となるスカラー値。
  22. * @return 計算したベクトル。
  23. */
  24. Vector operator *(const double& sca) const;
  25.  
  26. /**
  27. * スカラー値による除算を計算する。
  28. * @param sca 除数となるスカラー値。
  29. * @return 計算したベクトル。
  30. */
  31. Vector operator /(const double& sca) const;
  32.  
  33. /**
  34. * 二つのベクトルが等価かどうかを判定する。
  35. * @param vec 別のベクトル。
  36. * @return 等価ならtrue, 等価ではないならfalse。
  37. */
  38. bool operator ==(const Vector& vec) const;
  39.  
  40. /**
  41. * 二つのベクトルの外積を計算する。
  42. * @param vec 右側のベクトル。
  43. * @return 計算した外積。
  44. */
  45. Vector outpro(const Vector& rhs) const;
  46.  
  47. /**
  48. * 別のベクトルに射影する。
  49. * @param vec このベクトル上に射影する。
  50. * @return 射影したベクトル。
  51. */
  52. Vector project(const Vector& vec) const;
  53. };
  54.  
  55. /**
  56. * 二つの3次ベクトルの外積を計算する。3次ベクトル専用。
  57. * @param rhs 右側のベクトル。
  58. * @return 計算した外積。
  59. */
  60. template <>
  61. Vector<3> Vector<3>::outpro(const Vector<3>& rhs) const;
  62. };
  63.  
  64. namespace h3d {
  65. /**
  66. * 二つの数が近いかどうかを判定する。
  67. * @param x 一つ目の数。
  68. * @param y 二つ目の数。
  69. * @return 近いならtrue, 遠いならfalse。
  70. */
  71. inline bool near(const double& x, const double& y);
  72. };
  73.  
  74. #include <iostream>
  75. #include <string>
  76.  
  77. namespace h3d {
  78. using std::cout;
  79. using std::endl;
  80. using std::string;
  81.  
  82. #define ASSERT(pred) assert(#pred, (pred));
  83.  
  84. #define DEBUG_PRINT(val) cout << #val << "=" << (val) << endl;
  85.  
  86. /**
  87. * アサーションを実行する。
  88. * 成功なら標準出力に結果を出力する。
  89. * @param pred_str 判定する式を表した文字列。
  90. * @param pred_res 判定結果。trueなら成功,falseなら失敗と判定する。
  91. * @throw string 失敗ならメッセージをスローする。
  92. */
  93. inline void assert(const string& pred_str, const bool& pred_res) throw(string);
  94. };
  95.  
  96. namespace h3d {
  97. class Test { public: virtual void run() const = 0; };
  98. };
  99.  
  100. #include <memory>
  101. #include <vector>
  102.  
  103. namespace h3d {
  104. using std::shared_ptr;
  105. using std::vector;
  106.  
  107. class TestSet {
  108. public:
  109. TestSet();
  110. void run() const;
  111. protected:
  112. vector<shared_ptr<Test>> tests;
  113. };
  114. };
  115.  
  116. namespace h3d {
  117. class Test1 : public Test {
  118. public:
  119. virtual void run() const override;
  120. };
  121. };
  122.  
  123. ////////////////////////////////////////////////////////////////////////////////
  124.  
  125. namespace h3d {
  126. void Test1::run() const {
  127. Vector<3> p{2, 2, 1}, q{1, -2, 0};
  128. ASSERT(near(p.f[0], 2))
  129. ASSERT(near(p.f[1], 2))
  130. ASSERT(near(p.f[2], 1))
  131. ASSERT(near(q.f[0], 1))
  132. ASSERT(near(q.f[1], -2))
  133. ASSERT(near(q.f[2], 0))
  134. ASSERT(p * 2 == (Vector<3>{2 * 2.0, 2 * 2.0, 1 * 2.0}))
  135. ASSERT(q * -3 == (Vector<3>{1 * -3.0, -2 * -3.0, 0 * -3.0}))
  136. ASSERT(p / 2 == (Vector<3>{2 / 2.0, 2 / 2.0, 1 / 2.0}))
  137. ASSERT(q / -3 == (Vector<3>{1 / -3.0, -2 / -3.0, 0 / -3.0}))
  138. ASSERT(near(p.inpro(q), -2))
  139. ASSERT(p.outpro(q) == (Vector<3>{2, 1, -6}))
  140. ASSERT(p.project(q) == q * -2 / 5)
  141. ASSERT(q.project(p) == p * -2 / 9)
  142. }
  143. };
  144.  
  145. #include <memory>
  146.  
  147. namespace h3d {
  148. using std::shared_ptr;
  149.  
  150. TestSet::TestSet() {
  151. this->tests.push_back(shared_ptr<Test>(new Test1));
  152. }
  153.  
  154. void TestSet::run() const { for (auto iter : this->tests) iter->run(); }
  155. };
  156.  
  157. #include <utility>
  158.  
  159. namespace h3d {
  160. using std::move;
  161.  
  162. template <unsigned int N>
  163. double Vector<N>::inpro(const Vector& rhs) const {
  164. double res = 0;
  165. // 対応する成分同士の積を求めて、合計する。
  166. for (auto i = 0; i < N; i++) res += this->f[i] * rhs.f[i];
  167. return res;
  168. }
  169.  
  170. template <unsigned int N>
  171. Vector<N> Vector<N>::operator *(const double& sca) const {
  172. Vector<N> res;
  173. // それぞれの成分にスカラー値を掛ける。
  174. for (auto i = 0; i < N; i++) res.f[i] = this->f[i] * sca;
  175. return move(res);
  176. }
  177.  
  178. template <unsigned int N>
  179. Vector<N> Vector<N>::operator /(const double& sca) const {
  180. Vector<N> res;
  181. // それぞれの成分をスカラー値で割る。
  182. for (auto i = 0; i < N; i++) res.f[i] = this->f[i] / sca;
  183. return move(res);
  184. }
  185.  
  186. template <unsigned int N>
  187. bool Vector<N>::operator ==(const Vector& vec) const {
  188. bool res = true;
  189. if (&vec != this) {
  190. // すべての対応する成分が近ければ等価と判定する。
  191. for (auto i = 0; i < N; i++) {
  192. if (!near(this->f[i], vec.f[i])) {
  193. res = false;
  194. break;
  195. }
  196. }
  197. }
  198. return res;
  199. }
  200.  
  201. template <>
  202. Vector<3> Vector<3>::outpro(const Vector<3>& rhs) const {
  203. // それぞれの成分について、対応する列を除いた2×2の行列式を計算する。
  204. // P×Q = < Py・Qz - Pz・Qy, Pz・Qx - Px・Qz, Px・Qy - Py・Qx >
  205. return move(Vector<3>{
  206. this->f[1] * rhs.f[2] - this->f[2] * rhs.f[1],
  207. this->f[2] * rhs.f[0] - this->f[0] * rhs.f[2],
  208. this->f[0] * rhs.f[1] - this->f[1] * rhs.f[0],
  209. });
  210. }
  211.  
  212. template <unsigned int N>
  213. Vector<N> Vector<N>::project(const Vector& vec) const {
  214. // PをQ上に射影した結果は次式で与えられる。
  215. // P・Q
  216. // -----・Q
  217. // |Q|^2
  218. return move(vec * inpro(vec) / vec.inpro(vec));
  219. }
  220. };
  221.  
  222. namespace h3d {
  223. inline bool near(const double& x, const double& y) {
  224. static const double NEAR_THRESHOLD = 0.0000001;
  225. double dif = x - y;
  226. return dif > -NEAR_THRESHOLD && dif < NEAR_THRESHOLD;
  227. }
  228. };
  229.  
  230. #include <iostream>
  231. #include <string>
  232.  
  233. namespace h3d {
  234. using std::cout;
  235. using std::endl;
  236. using std::string;
  237.  
  238. inline void assert(const string& pred_str, const bool& pred_res) throw(string) {
  239. if (pred_res) cout << "アサート成功: " << pred_str << endl;
  240. else throw "アサート失敗: " + pred_str;
  241. }
  242. };
  243.  
  244. #include <iostream>
  245. #include <string>
  246.  
  247. int main() {
  248. using std::cerr;
  249. using std::endl;
  250. using std::string;
  251.  
  252. try {
  253. h3d::TestSet().run();
  254. }
  255. catch (const string& msg) {
  256. cerr << msg << endl;
  257. return 1;
  258. }
  259. return 0;
  260. }
  261.  
Success #stdin #stdout 0s 3440KB
stdin
Standard input is empty
stdout
アサート成功: near(p.f[0], 2)
アサート成功: near(p.f[1], 2)
アサート成功: near(p.f[2], 1)
アサート成功: near(q.f[0], 1)
アサート成功: near(q.f[1], -2)
アサート成功: near(q.f[2], 0)
アサート成功: p * 2 == (Vector<3>{2 * 2.0, 2 * 2.0, 1 * 2.0})
アサート成功: q * -3 == (Vector<3>{1 * -3.0, -2 * -3.0, 0 * -3.0})
アサート成功: p / 2 == (Vector<3>{2 / 2.0, 2 / 2.0, 1 / 2.0})
アサート成功: q / -3 == (Vector<3>{1 / -3.0, -2 / -3.0, 0 / -3.0})
アサート成功: near(p.inpro(q), -2)
アサート成功: p.outpro(q) == (Vector<3>{2, 1, -6})
アサート成功: p.project(q) == q * -2 / 5
アサート成功: q.project(p) == p * -2 / 9