#ifndef __FIXEDP_H__ #define __FIXEDP_H__ #include /** * 固定長小数クラス * ゲームではintをシフトして小数を表現するのが常識らしいので、 * 気持ち悪いシフト演算を隠蔽するクラスを作ってみようかと。 * 入力は double で、出力は int 。 * 内部表現は int だが小数も扱える、とのこと。 * int は 32 ビットじゃないと困ると思う。 * シフト数はテンプレート引数で指定。 * 当然 VC では通らんです。 */ template class FixedPoint { private: /** * コンパイルタイムなシフト変換。 * 実行速度に影響しない。 */ //@{ template struct ConvertHelper_; template struct ConvertHelper_ { static Int_ run(Int_ v) { return v; } }; template struct ConvertHelper_ { static Int_ run(Int_ v) { return v << leftShifts_ - rightShifts_; } }; template struct ConvertHelper_ { static Int_ run(Int_ v) { return v >> rightShifts_ - leftShifts_; } }; template Int_ convert_(Int_ v) const { return ConvertHelper_ <(leftShifts_ == rightShifts_), (leftShifts_ > rightShifts_), leftShifts_, rightShifts_>::run(v); } //@} template static Int_ conv(T v) { return static_cast(v * (1 << shifts_)); } public: Int_ val; FixedPoint() : val(0) {} template FixedPoint(ValueType v) : val(conv(v)){} FixedPoint(Int_ v) : val(v << shifts_){} template explicit FixedPoint(const FixedPoint &v){ val = convert_(v.val); } operator Int_() const{return val;} Int_ get() const{return val >> shifts_;} operator double() const{return (double)val / (1 << shifts_);} operator float() const{return (float)val / (1 << shifts_);} FixedPoint& operator = (const Int_ &v) { val = v << shifts_; return *this; } template FixedPoint& operator = (const FixedPoint &v) { val = convert_(v.val); return *this; } FixedPoint& operator += (const Int_ &v) { val += v << shifts_; return *this; } template FixedPoint& operator += (const FixedPoint &v) { val += convert_(v.val); return *this; } FixedPoint& operator -= (const Int_ &v) { val -= v << shifts_; return *this; } template FixedPoint& operator -= (const FixedPoint &v) { val -= convert_(v.val); return *this; } FixedPoint& operator *= (const Int_ &v) { val *= v; return *this; } template FixedPoint& operator *= (const FixedPoint &v) { val *= v.val; val >>= shifts2_; return *this; } FixedPoint& operator /= (const Int_ &v) { val /= v; return *this; } template FixedPoint& operator /= (const FixedPoint &v) { val <<= shifts2_; val /= v.val; return *this; } FixedPoint operator + (const Int_ &rhs) const { FixedPoint ret(*this); ret += rhs; return ret; } friend inline FixedPoint operator + (Int_ lhs, FixedPoint rhs) { return rhs.operator+(lhs); } template FixedPoint operator + (const FixedPoint &rhs) const{ FixedPoint ret(*this); ret += rhs; return ret; } FixedPoint operator-() const{ FixedPoint ret(*this); return ret * -1; } FixedPoint operator - (const Int_ &rhs) const{ FixedPoint ret(*this); ret -= rhs; return ret; } friend inline FixedPoint operator - (Int_ lhs, FixedPoint rhs) { FixedPoint ret(lhs); ret -= rhs; return ret; } template FixedPoint operator - (const FixedPoint &rhs) const{ FixedPoint ret(*this); ret -= rhs; return ret; } FixedPoint operator * (const Int_ &rhs) const{ FixedPoint ret(*this); ret *= rhs; return ret; } friend inline FixedPoint operator * (Int_ lhs, FixedPoint rhs){ return rhs.operator * (lhs); } template FixedPoint operator * (const FixedPoint &rhs) const{ FixedPoint ret(*this); ret *= rhs; return ret; } FixedPoint operator / (const Int_ &rhs) const{ FixedPoint ret(*this); ret /= rhs; return ret; } friend inline FixedPoint operator / (const Int_ &lhs, const FixedPoint &rhs) { FixedPoint ret(lhs); ret /= rhs; return ret; } template FixedPoint operator / (const FixedPoint &rhs) const{ FixedPoint ret(*this); ret /= rhs; return ret; } bool operator > (const Int_ &rhs) const{ return operator>(FixedPoint(rhs)); } template bool operator > (const FixedPoint &rhs) const{ return val > convert_(rhs.val); } bool operator < (const Int_ &rhs) const{ return operator<(FixedPoint(rhs)); } template bool operator < (const FixedPoint &rhs) const{ return val < convert_(rhs.val); } bool operator == (const Int_ &rhs) const{ return operator==(FixedPoint(rhs)); } template bool operator == (const FixedPoint &rhs) const{ return val == convert_(rhs.val); } inline bool operator != (const Int_ &rhs) const{ return !(operator==(FixedPoint(rhs))); } template inline bool operator != (const FixedPoint &rhs) const{ return val != convert_(rhs.val); } bool operator <= (const Int_ &rhs) const{ return operator<=(FixedPoint(rhs)); } template bool operator <= (const FixedPoint &rhs) const{ return val <= convert_(rhs.val); } bool operator >= (const Int_ &rhs) const{ return operator>=(FixedPoint(rhs)); } template bool operator >= (const FixedPoint &rhs) const{ return val >= convert_(rhs.val); } friend inline FixedPoint pow(FixedPoint v, int loop){ FixedPoint ret(v); for(; loop > 0; loop--){ret *= v;} return v; } #define MAKE_RAPPER(func) \ friend inline FixedPoint func(FixedPoint v){ \ return FixedPoint(func((double)v)); \ } MAKE_RAPPER(sqrt); MAKE_RAPPER(cos); MAKE_RAPPER(sin); #undef MAKE_RAPPER friend std::ostream &operator<<(std::ostream &out, const FixedPoint &v){ out << (double)v; return out; } }; #endif /* __FIXEDP_H__ */