#ifndef Juna_Fixed_Point_Number_H_ #define Juna_Fixed_Point_Number_H_ namespace Juna { //インラインアセンブラのシフト命令のためdefineで #define FixedShiftNum 10 //VC++用 インラインアセンブラでreturnが無い関数警告対応 #pragma warning(push) #pragma warning( disable : 4035 ) class Fixed { public: enum {FixedShift = FixedShiftNum}; typedef long int32; // Fixed(Fixed fixed) : Value(fixed.Value) {} Fixed(void) {} explicit Fixed(int32 val) : Value(val << FixedShift) {} explicit Fixed(int val) : Value(val << FixedShift) {} explicit Fixed(double val) : Value(static_cast(val * (1 << FixedShift))) {} //直接値を設定したいとき struct direct_tag {}; Fixed(int32 directvalue,direct_tag) : Value(directvalue) {} //分数で設定 Fixed(int32 numerator,int32 denominator) : Value((numerator << FixedShift) / denominator) {} Fixed &operator=(Fixed rhs) {Value = rhs.Value;return *this;} Fixed &operator=(int32 rhs) {Value = rhs << FixedShift;return *this;} // + Fixed &operator+=(Fixed rhs) {Value += rhs.Value;return *this;} Fixed &operator+=(int32 rhs) {Value += rhs << FixedShift;return *this;} const Fixed operator+(int32 rhs) const {return Fixed(*this) += rhs;} friend const Fixed operator+(int32 lhs,Fixed rhs) {return Fixed(lhs) += rhs;} const Fixed operator+(Fixed rhs) const {return Fixed(*this) += rhs;} // - Fixed &operator-=(Fixed rhs) {Value -= rhs.Value;return *this;} Fixed &operator-=(int32 rhs) {Value -= rhs << FixedShift;return *this;} const Fixed operator-(int32 rhs) const {return Fixed(*this) -= rhs;} friend const Fixed operator-(int32 lhs,Fixed rhs) {return Fixed(lhs) -= lhs;} const Fixed operator-(Fixed rhs) const {return Fixed(*this) -= rhs;} // * Fixed &operator*=(Fixed rhs) {Value = Multiply(Value,rhs.Value);return *this;} Fixed &operator*=(int32 rhs) {Value *= rhs;return *this;} const Fixed operator*(int32 rhs) const {return Fixed(*this) *= rhs;} friend const Fixed operator*(int32 lhs,Fixed rhs) {return Fixed(rhs) *= lhs;} const Fixed operator*(Fixed rhs) const {return Fixed(*this) *= rhs;} // / Fixed &operator/=(Fixed rhs) {Value = Divide(Value,rhs.Value);return *this;} Fixed &operator/=(int32 rhs) {Value /= rhs;return *this;} const Fixed operator/(int32 rhs) const {return Fixed(*this) /= rhs;} friend const Fixed operator/(int32 lhs,Fixed rhs) {return Fixed(lhs) /= rhs;} const Fixed operator/(Fixed rhs) const {return Fixed(*this) /= rhs;} // << Fixed &operator<<=(int rhs) {Value <<= rhs;return *this;} const Fixed operator<<(int rhs) const {return Fixed(*this) <<= rhs;} // >> Fixed &operator>>=(int rhs) {Value >>= rhs;return *this;} const Fixed operator>>(int rhs) const {return Fixed(*this) >>= rhs;} //符号反転 const Fixed &SetNegative(void) {Value = -Value;return *this;} //符号反転値 const Fixed operator-(void) const {return Fixed(*this).SetNegative();} //比較 bool operator==(Fixed rhs) const {return Value == rhs.Value;} bool operator!=(Fixed rhs) const {return Value != rhs.Value;} bool operator<(Fixed rhs) const {return Value < rhs.Value;} bool operator>(Fixed rhs) const {return Value > rhs.Value;} bool operator<=(Fixed rhs) const {return Value <= rhs.Value;} bool operator>=(Fixed rhs) const {return Value >= rhs.Value;} bool operator==(int32 rhs) const {return Value == rhs << FixedShift;} bool operator!=(int32 rhs) const {return Value != rhs << FixedShift;} bool operator<(int32 rhs) const {return Value < rhs << FixedShift;} bool operator>(int32 rhs) const {return Value > rhs << FixedShift;} bool operator<=(int32 rhs) const {return Value <= rhs << FixedShift;} bool operator>=(int32 rhs) const {return Value >= rhs << FixedShift;} //整数値 右シフト使ってるのがアレだけど int32 GetInt(void) const {return Value >> FixedShift;} //整数値 ちゃんと除算するので0に収束する int32 GetInt2(void) const {return Value / (1 << FixedShift);} //浮動小数点数 double GetDouble(void) const {return static_cast(Value) / (1 << FixedShift);} float GetFloat(void) const {return static_cast(Value) / (1 << FixedShift);} //保持している生の値 int32 GetFixedValue(void) const {return Value;} static Fixed Square(Fixed root) { int32 r; _asm { mov eax,root.Value; imul eax; shr eax,FixedShiftNum; shl edx,(32 - FixedShiftNum); or eax,edx; mov r,eax; } return Fixed(r,direct_tag()); } private: //実装 //インラインアセンブラで参照の実体を参照する方法が判らない static int32 Multiply(int32 lhs,int32 rhs) { // return (int32)(((__int64)lhs * rhs) >> FixedShiftNum); _asm { mov eax,lhs; imul rhs; shr eax,FixedShiftNum; shl edx,(32 - FixedShiftNum); or eax,edx; } } static int32 Divide(int32 lhs,int32 rhs) { // return (int32)(((__int64)lhs << FixedShiftNum) / rhs); _asm { mov eax,lhs; mov edx,eax; sar edx,(32 - FixedShiftNum); sal eax,FixedShiftNum; idiv rhs; } } private: //データ int32 Value; }; #pragma warning(pop) //念のためundef #undef FixedShiftNum }// namespace Juna #endif