Last active
April 28, 2020 14:10
-
-
Save lemon32767/7706144cd379e2de6f3edf7d7aad7a30 to your computer and use it in GitHub Desktop.
16:16 fixed point
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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