302 lines
7.5 KiB
C++
302 lines
7.5 KiB
C++
|
|
template<int ScalingFactor>
|
|
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<int64_t>(v * ScalingFactor)) {}
|
|
|
|
constexpr FixedPoint(double v) : val_(static_cast<int64_t>(v * ScalingFactor)) {}
|
|
|
|
constexpr FixedPoint(long double v) : val_(static_cast<int64_t>(v * ScalingFactor)) {}
|
|
|
|
constexpr double toDouble() {
|
|
return static_cast<double>(val_) / ScalingFactor;
|
|
}
|
|
|
|
constexpr int64_t toInt() {
|
|
return val_ / ScalingFactor;
|
|
}
|
|
|
|
constexpr int GetScalingFactor() {
|
|
return ScalingFactor;
|
|
}
|
|
|
|
constexpr int64_t GetUnderlyingValue() {
|
|
return val_;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> abs() const {
|
|
FixedPoint<ScalingFactor> res;
|
|
res.val_ = std::abs(val_);
|
|
return res;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> exp10(int exp) {
|
|
FixedPoint<ScalingFactor> 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<int64_t>::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<ScalingFactor> operator-() {
|
|
FixedPoint<ScalingFactor> res;
|
|
res.val_ = -val_;
|
|
return res;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator+=(const FixedPoint<ScalingFactor> &rhs) {
|
|
val_ += rhs.val_;
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator+=(int rhs) {
|
|
*this += FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator+=(double rhs) {
|
|
*this += FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator-=(const FixedPoint<ScalingFactor> &rhs) {
|
|
val_ -= rhs.val_;
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator-=(int rhs) {
|
|
*this -= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator-=(double rhs) {
|
|
*this -= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator*=(const FixedPoint<ScalingFactor> &rhs) {
|
|
val_ = val_ * rhs.val_ / ScalingFactor;
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator*=(int rhs) {
|
|
*this *= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator*=(double rhs) {
|
|
*this *= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator/=(const FixedPoint<ScalingFactor> &rhs) {
|
|
val_ = val_ * ScalingFactor / rhs.val_;
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator/=(int rhs) {
|
|
*this /= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr FixedPoint<ScalingFactor> &operator/=(double rhs) {
|
|
*this /= FixedPoint<ScalingFactor>(rhs);
|
|
return *this;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator+(FixedPoint<ScalingFactor> lhs,
|
|
const FixedPoint<ScalingFactor> &rhs) {
|
|
lhs += rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator-(FixedPoint<ScalingFactor> lhs,
|
|
const FixedPoint<ScalingFactor> &rhs) {
|
|
lhs -= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator*(FixedPoint<ScalingFactor> lhs,
|
|
const FixedPoint<ScalingFactor> &rhs) {
|
|
lhs *= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator/(FixedPoint<ScalingFactor> lhs,
|
|
const FixedPoint<ScalingFactor> &rhs) {
|
|
lhs /= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator+(FixedPoint<ScalingFactor> lhs, int rhs) {
|
|
lhs += rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator+(int lhs, FixedPoint<ScalingFactor> rhs) {
|
|
rhs += lhs;
|
|
return rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator+(FixedPoint<ScalingFactor> lhs, double rhs) {
|
|
lhs += rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator+(double lhs, FixedPoint<ScalingFactor> rhs) {
|
|
rhs += lhs;
|
|
return rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator-(FixedPoint<ScalingFactor> lhs, int rhs) {
|
|
lhs -= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator-(int lhs, FixedPoint<ScalingFactor> rhs) {
|
|
return FixedPoint<ScalingFactor>(lhs) - rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator-(FixedPoint<ScalingFactor> lhs, double rhs) {
|
|
lhs -= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator-(double lhs, FixedPoint<ScalingFactor> rhs) {
|
|
return FixedPoint<ScalingFactor>(lhs) - rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator*(FixedPoint<ScalingFactor> lhs, int rhs) {
|
|
lhs *= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator*(int lhs, FixedPoint<ScalingFactor> rhs) {
|
|
rhs *= lhs;
|
|
return rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator*(FixedPoint<ScalingFactor> lhs, double rhs) {
|
|
lhs *= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator*(double lhs, FixedPoint<ScalingFactor> rhs) {
|
|
rhs *= lhs;
|
|
return rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator/(FixedPoint<ScalingFactor> lhs, int rhs) {
|
|
lhs /= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator/(int lhs, FixedPoint<ScalingFactor> rhs) {
|
|
return FixedPoint<ScalingFactor>(lhs) / rhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator/(FixedPoint<ScalingFactor> lhs, double rhs) {
|
|
lhs /= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
constexpr friend FixedPoint<ScalingFactor> operator/(double lhs, FixedPoint<ScalingFactor> rhs) {
|
|
return FixedPoint<ScalingFactor>(lhs) / rhs;
|
|
}
|
|
|
|
constexpr friend bool operator<(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return lhs.val_ < rhs.val_;
|
|
}
|
|
|
|
constexpr friend bool operator>(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return rhs < lhs;
|
|
}
|
|
|
|
constexpr friend bool operator<=(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return !(lhs > rhs);
|
|
}
|
|
|
|
constexpr friend bool operator>=(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return !(lhs < rhs);
|
|
}
|
|
|
|
constexpr friend bool operator==(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return lhs.val_ == rhs.val_;
|
|
}
|
|
|
|
constexpr friend bool operator!=(FixedPoint<ScalingFactor> lhs, const FixedPoint<ScalingFactor> &rhs) {
|
|
return !(lhs == rhs);
|
|
}
|
|
|
|
}; |