Skip to content

Instantly share code, notes, and snippets.

@lemon32767
Last active April 28, 2020 14:10
Show Gist options
  • Save lemon32767/7706144cd379e2de6f3edf7d7aad7a30 to your computer and use it in GitHub Desktop.
Save lemon32767/7706144cd379e2de6f3edf7d7aad7a30 to your computer and use it in GitHub Desktop.
16:16 fixed point
#include <stdint.h>
#include <cstdio>
#include <iostream>
#include <cmath>
typedef struct fix32 {
int32_t n;
static const int32_t FACTOR = (1<<16);
//constructor
template <typename T> fix32(T v) { *this = v; /* use operator= */ }
fix32() { /*undefined*/ }
//construct number from raw integer value
static fix32 from_bits(int32_t i) {
fix32 tmp;
tmp.n = i;
return tmp;
}
//convert from type T to fix32
template <typename T>
static fix32 from(T n) {
return fix32::from_bits(n * T(FACTOR));
}
//convert from fix32 to type T
template <typename T>
T to() const {
return T(this->n) / T(FACTOR);
}
//set value performing conversion,
//this means you can do something like `fix32 x = 3.12` directly
template <typename T>
fix32& operator=(T n) {
this->n = fix32::from<T>(n).n;
return *this;
}
//same as .to<T>()
template <typename T>
explicit operator T() const {
return this->to<T>();
}
//conversions for output and input streams
friend std::ostream& operator<<(std::ostream& str, fix32 v) {
str << double(v);
return str;
}
friend std::istream& operator>>(std::istream& str, fix32& v) {
double tmp;
str >> tmp;
v = tmp;
return str;
}
//arithmetic operator overloading
friend fix32 operator+(fix32 a, fix32 b) {
return fix32::from_bits(a.n + b.n);
}
friend fix32 operator-(fix32 a, fix32 b) {
return fix32::from_bits(a.n - b.n);
}
friend fix32 operator-(fix32 a) {
return fix32::from_bits(-a.n);
}
friend fix32 operator*(fix32 a, fix32 b) {
float c = float(a.n) * float(b.n);
return fix32::from_bits(c / FACTOR);
}
friend fix32 operator/(fix32 a, fix32 b) {
return fix32::from_bits((float(a.n) * FACTOR) / float(b.n));
}
friend fix32 operator%(fix32 a, fix32 b) {
float c = std::fmod(float(a), float(b));
fix32 tmp = c;
return tmp;
}
#define __fix32_op_x_eq_templt(OP) \
friend fix32& operator OP##=(fix32& a, fix32 b) { \
a = a OP b; \
return a; \
}
__fix32_op_x_eq_templt(+) __fix32_op_x_eq_templt(-)
__fix32_op_x_eq_templt(*) __fix32_op_x_eq_templt(/)
__fix32_op_x_eq_templt(%)
#undef __fix32_op_x_eq_templt
#define __fix32_op_cmp_templt(OP) \
friend bool operator OP(fix32 a, fix32 b) { return a.n OP b.n; }
__fix32_op_cmp_templt(==) __fix32_op_cmp_templt(!=) __fix32_op_cmp_templt(>)
__fix32_op_cmp_templt(<) __fix32_op_cmp_templt(>=) __fix32_op_cmp_templt(<=)
#undef __fix32_op_cmp_templt
} fix32;
//example
#if 0
int main() {
fix32 a = 241.6;
a = a+3.007;
a *= 2;
fix32 b = a / 2;
b -= a/10;
a %= 100;
a = -a;
assert(a != b);
assert(a < b);
fix32 j = fix32::from_bits(0xFF912);
std::cout << sizeof(fix32) << "; " << a+j << ", " << b << ", " << fix32(-123.456) << std::endl;
std::cout << "gimme: ";
fix32 m;
std::cin >> m;
std::cout << m << "^2 = " << m*m << '\n';
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment