esp32displaytest/include/FixedPoint.h

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);
}
};