template class FixedPoint { int64_t val_; public: constexpr FixedPoint() : val_(0) {} constexpr FixedPoint(int64_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(int32_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(int16_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(int8_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(uint64_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(uint32_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(uint16_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(uint8_t v) : val_(v * ScalingFactor) {} constexpr FixedPoint(float v) : val_(static_cast(v * ScalingFactor)) {} constexpr FixedPoint(double v) : val_(static_cast(v * ScalingFactor)) {} constexpr FixedPoint(long double v) : val_(static_cast(v * ScalingFactor)) {} constexpr double toDouble() { return static_cast(val_) / ScalingFactor; } constexpr int64_t toInt() { return val_ / ScalingFactor; } constexpr int GetScalingFactor() { return ScalingFactor; } constexpr int64_t GetUnderlyingValue() { return val_; } constexpr FixedPoint abs() const { FixedPoint res; res.val_ = std::abs(val_); return res; } constexpr FixedPoint exp10(int exp) { FixedPoint res = *this; while(exp > 0) { res *= 10; exp--; } while (exp < 0) { res *= 10; exp++; } return res; } String toString(int min_decimal_digits = 0, bool zero_prefix_if_less_than_one = true) { if (val_ == 0) { return "0"; } constexpr int max_len = std::numeric_limits::max_digits10 + 2; // max digits plus decimal point and sign char c[max_len]; int len = 0; int64_t val = val_; bool negative = false; if (val < 0) { negative = true; val = -val; } int64_t decimal_part = val % ScalingFactor; if (decimal_part != 0) { while (decimal_part % 10 == 0) { decimal_part /= 10; } do { len += 1; c[max_len - len] = '0' + decimal_part % 10; decimal_part /= 10; } while (decimal_part > 0); len += 1; c[max_len - len] = '.'; } val /= ScalingFactor; do { len += 1; c[max_len - len] = '0' + val % 10; val /= 10; } while (val > 0); if (negative) { len += 1; c[max_len - len] = '-'; } return String(&c[max_len - len], len); } constexpr FixedPoint operator-() { FixedPoint res; res.val_ = -val_; return res; } constexpr FixedPoint &operator+=(const FixedPoint &rhs) { val_ += rhs.val_; return *this; } constexpr FixedPoint &operator+=(int rhs) { *this += FixedPoint(rhs); return *this; } constexpr FixedPoint &operator+=(double rhs) { *this += FixedPoint(rhs); return *this; } constexpr FixedPoint &operator-=(const FixedPoint &rhs) { val_ -= rhs.val_; return *this; } constexpr FixedPoint &operator-=(int rhs) { *this -= FixedPoint(rhs); return *this; } constexpr FixedPoint &operator-=(double rhs) { *this -= FixedPoint(rhs); return *this; } constexpr FixedPoint &operator*=(const FixedPoint &rhs) { val_ = val_ * rhs.val_ / ScalingFactor; return *this; } constexpr FixedPoint &operator*=(int rhs) { *this *= FixedPoint(rhs); return *this; } constexpr FixedPoint &operator*=(double rhs) { *this *= FixedPoint(rhs); return *this; } constexpr FixedPoint &operator/=(const FixedPoint &rhs) { val_ = val_ * ScalingFactor / rhs.val_; return *this; } constexpr FixedPoint &operator/=(int rhs) { *this /= FixedPoint(rhs); return *this; } constexpr FixedPoint &operator/=(double rhs) { *this /= FixedPoint(rhs); return *this; } constexpr friend FixedPoint operator+(FixedPoint lhs, const FixedPoint &rhs) { lhs += rhs; return lhs; } constexpr friend FixedPoint operator-(FixedPoint lhs, const FixedPoint &rhs) { lhs -= rhs; return lhs; } constexpr friend FixedPoint operator*(FixedPoint lhs, const FixedPoint &rhs) { lhs *= rhs; return lhs; } constexpr friend FixedPoint operator/(FixedPoint lhs, const FixedPoint &rhs) { lhs /= rhs; return lhs; } constexpr friend FixedPoint operator+(FixedPoint lhs, int rhs) { lhs += rhs; return lhs; } constexpr friend FixedPoint operator+(int lhs, FixedPoint rhs) { rhs += lhs; return rhs; } constexpr friend FixedPoint operator+(FixedPoint lhs, double rhs) { lhs += rhs; return lhs; } constexpr friend FixedPoint operator+(double lhs, FixedPoint rhs) { rhs += lhs; return rhs; } constexpr friend FixedPoint operator-(FixedPoint lhs, int rhs) { lhs -= rhs; return lhs; } constexpr friend FixedPoint operator-(int lhs, FixedPoint rhs) { return FixedPoint(lhs) - rhs; } constexpr friend FixedPoint operator-(FixedPoint lhs, double rhs) { lhs -= rhs; return lhs; } constexpr friend FixedPoint operator-(double lhs, FixedPoint rhs) { return FixedPoint(lhs) - rhs; } constexpr friend FixedPoint operator*(FixedPoint lhs, int rhs) { lhs *= rhs; return lhs; } constexpr friend FixedPoint operator*(int lhs, FixedPoint rhs) { rhs *= lhs; return rhs; } constexpr friend FixedPoint operator*(FixedPoint lhs, double rhs) { lhs *= rhs; return lhs; } constexpr friend FixedPoint operator*(double lhs, FixedPoint rhs) { rhs *= lhs; return rhs; } constexpr friend FixedPoint operator/(FixedPoint lhs, int rhs) { lhs /= rhs; return lhs; } constexpr friend FixedPoint operator/(int lhs, FixedPoint rhs) { return FixedPoint(lhs) / rhs; } constexpr friend FixedPoint operator/(FixedPoint lhs, double rhs) { lhs /= rhs; return lhs; } constexpr friend FixedPoint operator/(double lhs, FixedPoint rhs) { return FixedPoint(lhs) / rhs; } constexpr friend bool operator<(FixedPoint lhs, const FixedPoint &rhs) { return lhs.val_ < rhs.val_; } constexpr friend bool operator>(FixedPoint lhs, const FixedPoint &rhs) { return rhs < lhs; } constexpr friend bool operator<=(FixedPoint lhs, const FixedPoint &rhs) { return !(lhs > rhs); } constexpr friend bool operator>=(FixedPoint lhs, const FixedPoint &rhs) { return !(lhs < rhs); } constexpr friend bool operator==(FixedPoint lhs, const FixedPoint &rhs) { return lhs.val_ == rhs.val_; } constexpr friend bool operator!=(FixedPoint lhs, const FixedPoint &rhs) { return !(lhs == rhs); } };