#ifndef FASTMATH_H #define FASTMATH_H #include #include #include #include #define SHIFT_AMOUNT 16 #define HALF_SHIFT (SHIFT_AMOUNT / 2) #define SHIFT_MASK ((1 << SHIFT_AMOUNT) - 1) #define TO_FLOAT(x) \ (((float)(x >> SHIFT_AMOUNT)) + \ ((double)(x & SHIFT_MASK) / (1 << SHIFT_AMOUNT))) #define TO_INT(x) ((int32_t)(x * (1 << SHIFT_AMOUNT))) #define MUL_F(a, b) (((a) >> HALF_SHIFT) * ((b) >> HALF_SHIFT)) #define DIV_F(a, b) ((((a) << HALF_SHIFT) / (b)) << HALF_SHIFT) struct decimal { const int32_t i; decimal(float i) : i(TO_INT(i)) {} decimal(double i) : i(TO_INT(i)) {} decimal(int32_t i) : i(i) {} friend std::ostream &operator<<(std::ostream &os, const decimal &d) { return (os << TO_FLOAT(d.i)); } friend decimal operator+(const decimal &d1, const decimal &d2) { return {d1.i + d2.i}; } decimal &operator+=(const decimal &d) { return (*this) = {i + d.i}; } friend decimal operator-(const decimal &d1, const decimal &d2) { return {d1.i - d2.i}; } friend decimal operator-(const decimal &d) { return {-d.i}; } friend decimal operator*(const decimal &d1, const decimal &d2) { return {MUL_F(d1.i, d2.i)}; } friend decimal operator/(const decimal &d1, const decimal &d2) { return {DIV_F(d1.i, d2.i)}; } friend bool operator<(const decimal &d1, const decimal &d2) { return d1.i < d2.i; } friend bool operator>(const decimal &d1, const decimal &d2) { return d1.i > d2.i; } friend bool operator==(const decimal &d1, const decimal &d2) { return d1.i == d2.i; } decimal &operator=(decimal const &in) { if (this != &in) { std::destroy_at(this); std::construct_at(this, in); } return *this; } decimal sqrt() { return {((int32_t)sqrtf(i)) << HALF_SHIFT}; } float to_float() { return TO_FLOAT(i); } }; struct vec3 { const decimal x; const decimal y; const decimal z; vec3(float x, float y, float z) : x(decimal(x)), y(decimal(y)), z(decimal(z)) {} vec3(double x, double y, double z) : x(decimal(x)), y(decimal(y)), z(decimal(z)) {} vec3(int32_t x, int32_t y, int32_t z) : x(decimal(x)), y(decimal(y)), z(decimal(z)) {} vec3(decimal x, decimal y, decimal z) : x(x), y(y), z(z) {} friend vec3 operator+(const vec3 &v1, const vec3 &v2) { return vec3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); } friend vec3 operator-(const vec3 &v1, const vec3 &v2) { return vec3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); } vec3 operator-() { return vec3(-x, -y, -z); } friend vec3 operator*(const vec3 &v, const decimal &n) { int32_t f = n.i >> HALF_SHIFT; return vec3({(v.x.i >> HALF_SHIFT) * f}, {(v.y.i >> HALF_SHIFT) * f}, {(v.z.i >> HALF_SHIFT) * f}); } friend vec3 operator*(const decimal &n, const vec3 &v) { return v * n; } decimal operator*(const vec3 &v) { return v.x * x + v.y * y + v.z * z; } friend bool operator==(const vec3 &v1, const vec3 &v2) { return (v1.x == v2.x) & (v1.y == v2.y) & (v1.z == v2.z); } vec3 &operator=(vec3 const &in) { if (this != &in) { std::destroy_at(this); std::construct_at(this, in); } return *this; } friend std::ostream &operator<<(std::ostream &os, const vec3 &v) { return (os << "(" << v.x << ", " << v.y << ", " << v.z << ")" << std::endl); } vec3 cross(const vec3 &v) { return vec3((y * v.z) - (z * v.y), (z * v.x) - (x * v.z), (x * v.y) - (y * v.x)); } decimal len_sq() { return *this * *this; } decimal len() { return this->len_sq().sqrt(); } vec3 normalize() { decimal f = decimal(1.0) / this->len(); return (*this * f); } }; #endif