finish fixed point

v1
Brett 2024-04-04 18:23:34 -04:00
parent 27af4e339f
commit 26d215be0a
3 changed files with 200 additions and 68 deletions

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
include(cmake/color.cmake) include(cmake/color.cmake)
set(BLT_VERSION 0.16.4) set(BLT_VERSION 0.16.5)
set(BLT_TEST_VERSION 0.0.1) set(BLT_TEST_VERSION 0.0.1)
set(BLT_TARGET BLT) set(BLT_TARGET BLT)

View File

@ -20,140 +20,232 @@
#define BLT_FIXED_POINT_H #define BLT_FIXED_POINT_H
#include <blt/std/types.h> #include <blt/std/types.h>
#include <blt/std/utility.h> //#include <blt/std/utility.h>
#define BLT_DEBUG_NO_INLINE BLT_ATTRIB_NO_INLINE //#define BLT_DEBUG_NO_INLINE BLT_ATTRIB_NO_INLINE
#define BLT_DEBUG_NO_INLINE
namespace blt namespace blt
{ {
struct fp64 struct fp64
{ {
private: private:
u64 v = 0; i64 v = 0;
fp64() = default; constexpr fp64() = default;
public:
explicit fp64(u64 v): v(v) constexpr explicit fp64(u64 ui): v(from_u64(ui))
{} {}
public: constexpr explicit fp64(i64 si): v(from_i64(si))
static fp64 from_u64(u64 ui) {}
constexpr explicit fp64(u32 ui): v(from_u32(ui))
{}
constexpr explicit fp64(i32 si): v(from_i32(si))
{}
constexpr explicit fp64(f32 f): v(from_f32(f))
{}
constexpr explicit fp64(f64 d): v(from_f64(d))
{}
constexpr static inline fp64 from_raw(i64 i)
{
fp64 r;
r.v = i;
return r;
}
constexpr static inline fp64 from_raw_u64(u64 u)
{
fp64 r;
r.v = static_cast<i64>(u);
return r;
}
constexpr static inline fp64 from_u64(u64 ui)
{
return from_i64(static_cast<i64>(ui));
}
constexpr static inline fp64 from_i64(i64 si)
{
return from_raw(si << 32);
}
constexpr static inline fp64 from_u32(u32 ui)
{
return from_i64(static_cast<i64>(ui));
}
constexpr static inline fp64 from_i32(i32 si)
{
return from_i64(static_cast<i64>(si));
}
constexpr static inline fp64 from_f64(f64 d)
{ {
fp64 fp; fp64 fp;
fp.v = ui << 32; fp.v = static_cast<i64>(d * (1ul << 32ul));
return fp; return fp;
} }
static fp64 from_i64(i64 si) constexpr static inline fp64 from_f32(f32 f)
{
u64 ui = static_cast<u64>(si);
fp64 fp;
fp.v = ui << 32;
return fp;
}
static fp64 from_f64(f64 d)
{
fp64 fp;
fp.v = static_cast<u64>(d * (1ul << 32ul));
return fp;
}
static fp64 from_f32(f32 f)
{ {
return from_f64(static_cast<double>(f)); return from_f64(static_cast<double>(f));
} }
BLT_DEBUG_NO_INLINE friend fp64 operator+(fp64 left, fp64 right) BLT_DEBUG_NO_INLINE constexpr friend inline fp64 operator+(fp64 left, fp64 right)
{ {
return fp64(left.v + right.v); return from_raw(left.v + right.v);
} }
BLT_DEBUG_NO_INLINE friend fp64 operator-(fp64 left, fp64 right) BLT_DEBUG_NO_INLINE constexpr friend inline fp64 operator-(fp64 left, fp64 right)
{ {
return fp64(left.v - right.v); return from_raw(left.v - right.v);
} }
BLT_DEBUG_NO_INLINE friend fp64 operator*(fp64 left, fp64 right) BLT_DEBUG_NO_INLINE constexpr friend inline fp64 operator*(fp64 left, fp64 right)
{ {
auto lhs = static_cast<unsigned __int128>(left.v); auto lhs = static_cast<__int128>(left.v);
auto rhs = static_cast<unsigned __int128>(right.v); auto rhs = static_cast<__int128>(right.v);
return fp64(static_cast<u64>((lhs * rhs) >> 32)); return from_raw(static_cast<i64>((lhs * rhs) >> 32));
} }
BLT_DEBUG_NO_INLINE friend fp64 operator/(fp64 left, fp64 right) BLT_DEBUG_NO_INLINE constexpr friend inline fp64 operator/(fp64 left, fp64 right)
{ {
auto lhs = static_cast<unsigned __int128>(left.v) << 32; auto lhs = static_cast<__int128>(left.v) << 32;
auto rhs = static_cast<unsigned __int128>(right.v); return from_raw(static_cast<i64>(lhs / right.v));
return fp64(static_cast<u64>(lhs / rhs));
} }
[[nodiscard]] inline u64 as_u64() const BLT_DEBUG_NO_INLINE constexpr inline fp64& operator+=(fp64 add)
{
v += add.v;
return *this;
}
BLT_DEBUG_NO_INLINE constexpr inline fp64& operator-=(fp64 sub)
{
v -= sub.v;
return *this;
}
BLT_DEBUG_NO_INLINE constexpr inline fp64& operator*=(fp64 mul)
{
auto lhs = static_cast<__int128>(v);
auto rhs = static_cast<__int128>(mul.v);
v = static_cast<i64>((lhs * rhs) >> 32);
return *this;
}
BLT_DEBUG_NO_INLINE constexpr inline fp64& operator/=(fp64 div)
{
auto lhs = static_cast<__int128>(v) << 32;
v = static_cast<i64>(lhs / div.v);
return *this;
}
[[nodiscard]] constexpr inline u64 as_u64() const
{
return static_cast<u64>(v) >> 32;
}
[[nodiscard]] constexpr inline i64 as_i64() const
{ {
return v >> 32; return v >> 32;
} }
[[nodiscard]] inline i64 as_i64() const [[nodiscard]] constexpr inline u32 as_u32() const
{ {
return static_cast<i64>(as_u64()); return static_cast<u32>(v >> 32);
} }
[[nodiscard]] inline u32 as_u32() const [[nodiscard]] constexpr inline i32 as_i32() const
{ {
return static_cast<u32>(as_u64()); return static_cast<i32>(v >> 32);
} }
[[nodiscard]] inline i32 as_i32() const [[nodiscard]] constexpr inline f64 as_f64() const
{
return static_cast<i32>(as_u64());
}
[[nodiscard]] inline f64 as_f64() const
{ {
return static_cast<f64>(v) / static_cast<f64>(1ul << 32ul); return static_cast<f64>(v) / static_cast<f64>(1ul << 32ul);
} }
[[nodiscard]] inline f32 as_f32() const [[nodiscard]] constexpr inline f32 as_f32() const
{ {
return static_cast<f32>(as_f64()); return static_cast<f32>(v) / static_cast<f32>(1ul << 32ul);
} }
inline explicit operator u64() const constexpr inline explicit operator u64() const
{ {
return as_u64(); return as_u64();
} }
inline explicit operator i64() const constexpr inline explicit operator i64() const
{ {
return as_i64(); return as_i64();
} }
inline explicit operator u32() const constexpr inline explicit operator u32() const
{ {
return as_u32(); return as_u32();
} }
inline explicit operator i32() const constexpr inline explicit operator i32() const
{ {
return as_i32(); return as_i32();
} }
inline explicit operator f32() const constexpr inline explicit operator f32() const
{ {
return as_f32(); return as_f32();
}; };
inline explicit operator f64() const constexpr inline explicit operator f64() const
{ {
return as_f64(); return as_f64();
} }
[[nodiscard]] u64 raw() const [[nodiscard]] constexpr u64 raw() const
{ {
return v; return v;
} }
}; };
// max unsigned integer value
static constexpr const inline fp64 FP64_UMAX = fp64::from_raw_u64(0xFFFFFFFF00000000);
// min unsigned integer value
static constexpr const inline fp64 FP64_UMIN = fp64::from_raw_u64(0x0000000000000000);
// max signed integer value
static constexpr const inline fp64 FP64_IMAX = fp64::from_raw_u64(0x7FFFFFFF00000000);
// min signed integer value
static constexpr const inline fp64 FP64_IMIN = fp64::from_raw_u64(0x8000000000000000);
// max value storable including floating point
static constexpr const inline fp64 FP64_FMAX = fp64::from_raw_u64(0x7FFFFFFFFFFFFFFF);
// min float point number
static constexpr const inline fp64 FP64_FMIN = fp64::from_raw_u64(0x8000000000000000);
// smallest decimal number
static constexpr const inline fp64 FP64_EPSILON = fp64::from_raw_u64(0x0000000000000001);
// pi
static constexpr const inline fp64 FP64_PI = fp64::from_f64(3.14159265358979323846);
// pi / 2
static constexpr const inline fp64 FP64_PI_2 = fp64::from_f64(1.57079632679489661923);
// pi / 4
static constexpr const inline fp64 FP64_PI_4 = fp64::from_f64(0.78539816339744830962);
// 1 / pi
static constexpr const inline fp64 FP64_1_PI = fp64::from_f64(0.31830988618379067154);
// 2 / pi
static constexpr const inline fp64 FP64_2_PI = fp64::from_f64(0.63661977236758134308);
// sqrt(2)
static constexpr const inline fp64 FP64_SQRT2 = fp64::from_f64(1.41421356237309504880);
// 1 / sqrt(2)
static constexpr const inline fp64 FP64_1_SQRT2 = fp64::from_f64(0.70710678118654752440);
// e
static constexpr const inline fp64 FP64_E = fp64::from_f64(2.7182818284590452354f);
// log2(e)
static constexpr const inline fp64 FP64_LOG2E = fp64::from_f64(1.4426950408889634074f);
} }
#endif //BLT_FIXED_POINT_H #endif //BLT_FIXED_POINT_H

View File

@ -19,31 +19,71 @@
#include <blt/math/vectors.h> #include <blt/math/vectors.h>
#include <blt/std/logging.h> #include <blt/std/logging.h>
#include <iostream> #include <iostream>
#include <ios>
#include <blt_tests.h> #include <blt_tests.h>
#include <cmath> #include <cmath>
#include <iomanip>
#include <limits>
using vec3fp = blt::vec<blt::fp64, 3>; using vec3fp = blt::vec<blt::fp64, 3>;
namespace blt::test namespace blt::test
{ {
void print(fp64 v, const std::string& name = "")
{
std::cout << name << " [" << v.raw() << ':' << std::hex << v.raw() << std::dec << "]\tu64(" << v.as_u64() << ")\ti64(" << v.as_i64()
<< ")\tu32(" << v.as_u32() << ")\ti32(" << v.as_i32() << ")\tf32("
<< std::setprecision(std::numeric_limits<long double>::digits10 + 1)
<< std::setw(16) << std::fixed << v.as_f32() << ")\tf64(" << v.as_f64() << ")\n";
}
void fixed_point() void fixed_point()
{ {
//vec3fp hello = {fp64::from_f64(32.023), fp64::from_f64(422.34023), fp64::from_f64(321.023)}; //vec3fp hello = {fp64::from_f64(32.023), fp64::from_f64(422.34023), fp64::from_f64(321.023)};
print(FP64_UMAX, "umax");
print(FP64_UMIN, "umin");
print(FP64_IMAX, "imax");
print(FP64_IMIN, "imin");
print(FP64_FMAX, "fmax");
print(FP64_FMIN, "fmin");
print(FP64_EPSILON, "epis");
print(FP64_PI, "pi ");
print(FP64_PI_2, "pi2 ");
print(FP64_PI_4, "pi4 ");
print(FP64_1_PI, "1/pi");
print(FP64_2_PI, "1/p2");
print(FP64_SQRT2, "sqr2");
print(FP64_1_SQRT2, "isq2");
print(FP64_E, "e ");
print(FP64_LOG2E, "logE");
fp64 uv = fp64::from_u64(32); fp64 uv = fp64::from_u64(32);
fp64 iv = fp64::from_i64(16); fp64 iv = fp64::from_i64(16);
fp64 fv = fp64::from_f32(53.4234234); fp64 fv = fp64::from_f32(53.4234234);
fp64 pi = fp64::from_f64(M_PI); fp64 pi = fp64::from_f64(M_PI);
std::cout << "[" << static_cast<u64>(uv) << "]: " << uv.as_i64() << " : " << uv.as_u64() << " : " << uv.as_f64() << std::endl; print(uv * iv, "32 * 16");
std::cout << "[" << static_cast<u64>(iv) << "]: " << iv.as_i64() << " : " << iv.as_u64() << " : " << iv.as_f64() << std::endl; print(uv / iv, "32 / 16");
std::cout << "[" << static_cast<u64>(fv) << "]: " << fv.as_i64() << " : " << fv.as_u64() << " : " << fv.as_f64() << std::endl; print(fv / pi, "53.4234234 / pi");
std::cout << "[" << static_cast<u64>(pi) << "]: " << pi.as_i64() << " : " << pi.as_u64() << " : " << pi.as_f64() << std::endl;
std::cout << (uv * iv).as_i64() << std::endl; print(uv + iv, "32 + 16");
std::cout << (uv * iv).as_u64() << std::endl; print(uv - iv, "32 - 16");
std::cout << (uv / iv).as_i64() << std::endl;
std::cout << (uv / iv).as_u64() << std::endl; print(fp64::from_f32(32.43242), "32.43242");
print(fp64::from_f64(634.2349932493423), "634.2349932493423");
print(fp64::from_u32(3194967295), "3194967295");
print(fp64::from_i32(-1194967295), "-1194967295");
print(fp64::from_i64(-13194967295), "-13194967295");
print(fp64::from_u64(66294967295), "66294967295");
uv *= fp64::from_i32(-32);
print(uv);
uv /= fp64::from_i32(-16);
print(uv);
} }
} }