Nagarei / DxLibEx

DXライブラリC++化プロジェクト
Boost Software License 1.0
31 stars 3 forks source link

point_cクラスのcrossの仕様 #88

Open yumetodo opened 8 years ago

yumetodo commented 8 years ago

https://github.com/Nagarei/DxLibEx/blob/d8f29942a900d5f8c888dfeb99a6f64babcdd2b4/dxlibex/basic_types/point2d.hpp#L628

二次元ベクトルの外積は、二ベクトルのなす平行四辺形の面積(符号の話はおいておいて)で定義しているが、

default

これを作成した時の私は https://github.com/Nagarei/DxLibEx/commit/16271b650c77ec6df9ee6109b94121a1a7a6f322 double型にキャストして計算している。

計算式そのものは上図からsin/cosの定義とベクトルの内積と加法定理で証明できるから、pa.x * pb.y + pa.y * pb.xであっているけど、キャストはいらない気がしている。(中身掛け算と足し算ですし)

ただ、これを作るときに参考にしたOpenCVでは http://docs.opencv.org/master/db/d4e/classcv_1_1Point__.html#a946769d5545dba5d328486602aae2ac3 https://github.com/opencv/opencv/blob/c8693f01a3b557fdf0ccb4fd6bff2fe616e7ce32/modules/core/include/opencv2/core/types.hpp#L1117 doubleにキャストしている。

@Nagarei キャストどうしましょうか

Nagarei commented 8 years ago

キャストしているのはオーバーフロー対策ですね。 二乗の計算は意外とあっさりオーバーフローするので、少なくともデフォルト動作ではdoubleへのキャストは妥当だと思います。

yumetodo commented 8 years ago

@Nagarei

オーバーフロー対策

doublestd::uint64_tだと後者のほうが範囲広いんですよね・・・。

yumetodo commented 8 years ago

いずれにせよ 43ea90edc48ec8d9da8c93c1d95a46014f9cce34 でstatic_cast_ifを使うように書き換えてしまったのでオーバーフローを考えるならまずい

Nagarei commented 8 years ago

doubleは64bitのとき精度はかなり落ちますが、300桁以上の数値を扱えたはずなので、150桁までの数値なら二乗できるはずです。 とはいえuint64_tでも8.5e+9までの数値なら二乗できるので良いような気もしますが。

yumetodo commented 8 years ago

精度の問題があるのであまり浮動小数点型にキャストしたくないんですよね・・・。 まあ確かに精度を抜きにすればdoubleは最適解ですが・・・・。

たとえば、std::numeric_limits<std::int32_t>::max() < sqrt(std::numeric_limits<std::int64_t>::max())の関係が成り立つので、std::int32_tの入力ならstd::int64_tを返すほうがいい気がしますしということで

という手もあるかなと思うわけですが、実装が複雑になるか・・・。

Nagarei commented 8 years ago

なるほど。 仮実装でとりあえずdoubleにした後、上の動作が実装でき次第差し替えるというのはどうでしょう。

yumetodo commented 8 years ago

了解ですが、テストどうやって書こう・・・