固定小数点数クラス
OpenGL ES を使う上ですごく必要になってきたので作ってみた。
// 固定小数点数クラス(Q16) struct fixed { private: int32 v_; public: fixed() : v_(0) { } fixed(const fixed& f) : v_(f.v_) { } // implicit で大丈夫だよね?オーバーフローしないように注意すること。 fixed(int32 v) : v_(v << 16) { } // n/m を格納 fixed(int32 n, int32 m) : v_((int32)(((int64)n << 16) / m)) { } int32 get() const { return v_; } fixed& operator=(const fixed& f) { v_ = f.v_; return *this; } fixed operator+() const { return *this; } fixed operator-() const { fixed v; v.v_ = -v_; return v; } fixed& operator+=(const fixed& f) { v_ += f.v_; return *this; } fixed& operator-=(const fixed& f) { v_ -= f.v_; return *this; } fixed& operator*=(const fixed& f) { v_ = (v_ >> 8) * (f.v_ >> 8); return *this; } fixed& operator/=(const fixed& f) { v_ = (((int64)v_ << 32) / f.v_) >> 16; return *this; } fixed& operator>>=(int v) { v_ >>= v; return *this; } fixed& operator<<=(int v) { v_ <<= v; return *this; } }; inline fixed operator+(const fixed& a, const fixed& b) { fixed v(a); return v += b; } inline fixed operator-(const fixed& a, const fixed& b) { fixed v(a); return v -= b; } inline fixed operator*(const fixed& a, const fixed& b) { fixed v(a); return v *= b; } inline fixed operator/(const fixed& a, const fixed& b) { fixed v(a); return v /= b; } inline fixed operator>>(const fixed& a, int b) { fixed v(a); return v >>= b; } inline fixed operator<<(const fixed& a, int b) { fixed v(a); return v <<= b; } inline bool operator==(const fixed& a, const fixed& b) { return a.get() == b.get(); } inline bool operator!=(const fixed& a, const fixed& b) { return !(a == b); } inline bool operator<(const fixed& a, const fixed& b) { return a.get() < b.get(); } inline bool operator>(const fixed& a, const fixed& b) { return b < a; } inline bool operator<=(const fixed& a, const fixed& b) { return !(b < a); } inline bool operator>=(const fixed& a, const fixed& b) { return !(a < b); }
まあ、普通の実装かな?除算が重そうだけど。
でもこのクラス、コンストラクタが implicit なので、
class texture { public: uint32 width() const { ... } uint32 height() const { ... } ... }; draw(const texture& t, const fixed& x, const fixed& y);
こんなのがあったときに
texture t; fixed x,y; draw(t, x - t.width() / 2, y - t.height() / 2);
とか書けて結構便利だったりする。
ただ、時々意図しない変換が行われちゃったりするかもしれない(GLfixed と計算しようとした場合とか)のでその辺は注意する必要があったり。
GLfixed をセットしたかったら、
GLfixed glf;
fixed f(glf, 65536);
とか書く必要があるんだけど、やっぱり raw データをセットするコンストラクタがいるかなぁ……。
struct fixed { private: int32 v_; public: struct raw_tag { }; fixed(int32 v, raw_tag) : v_(v) { } ... };
GLfixed glf; fixed f(glf, fixed::raw_tag());
みたいな感じで。