Half-precision floating point serialization.

This commit is contained in:
2025-01-24 15:28:18 -05:00
parent 4909052c4d
commit e2e26a484b
3 changed files with 63 additions and 8 deletions

View File

@@ -15,6 +15,11 @@ namespace CaveGame::Core
uint8_t* data;
};
/// Converts a 16-bit unsigned integer into a floating point number. @see float_to_u16.
float u16_to_float(uint16_t value);
/// Converts a floating point number to a 16-bit unsigned integer. This in effect, drops the accuracy of the float in exchange for compression.
uint16_t float_to_u16(float);
/// Writes a 1-byte unsigned int to the buffer, in network-byte-order, and advances the index by 1.
void write_u8(Buffer& buffer, uint8_t value);
/// Writes a 2-byte unsigned int to the buffer, in network-byte-order, and advances the index by 2.
@@ -51,11 +56,13 @@ namespace CaveGame::Core
/// Reads a 8-byte signed int from the buffer, from network-byte-order, and advances the index by 8.
int64_t read_s64(Buffer& buffer);
void write_f16(Buffer& buffer, float value);
/// Writes a 4-byte float to the buffer, via reinterpreting as uint32_t, and advances the index by 4.
void write_f32(Buffer& buffer, float value);
/// Writes a 8-byte float to the buffer, via reinterpreting as uint64_t, and advances the index by 8.
void write_f64(Buffer& buffer, double value);
float read_f16(Buffer& buffer);
/// Reads a 4-byte float from the buffer, via reinterpreting from uint32_t, and advances the index by 4.
float read_f32(Buffer& buffer);
/// Reads a 8-byte float from the buffer, via reinterpreting from uint64_t, and advances the index by 8.

View File

@@ -156,6 +156,33 @@ namespace CaveGame::Core
using J3ML::ReinterpretAs;
float u16_to_float(uint16_t value)
{
union {
float f_number;
uint16_t uint16_arr[2];
} union_for_conv;
union_for_conv.f_number = 0;
union_for_conv.uint16_arr[1] = value;
return union_for_conv.f_number;
}
uint16_t float_to_u16(float value)
{
union {
float f_number;
uint16_t uint16_arr[2];
} union_for_conv;
union_for_conv.f_number = value;
uint16_t a = union_for_conv.uint16_arr[1];
return a;
}
void write_f16(Buffer& buffer, float value)
{
write_u16(buffer, float_to_u16(value));
}
void write_f32(Buffer &buffer, float value) {
write_u32(buffer, ReinterpretAs<uint32_t>(value));
}
@@ -164,6 +191,10 @@ namespace CaveGame::Core
write_u64(buffer, ReinterpretAs<uint64_t>(value));
}
float read_f16(Buffer& buffer) {
return u16_to_float(read_u16(buffer));
}
float read_f32(Buffer &buffer) {
return ReinterpretAs<float>(read_u32(buffer));
}

View File

@@ -163,6 +163,16 @@ public:
}
};
void rtt_f16(float input)
{
uint16_t intermediate = float_to_u16(input);
float returned = u16_to_float(intermediate);
std::cout << "Input: " << input << ", Output: " << returned << std::endl;
}
void roundtrip_test()
{
using namespace CaveGame::Core;
@@ -187,18 +197,25 @@ void roundtrip_test()
write_u32(test, c);
write_u64(test, d);
write_s8(test, e);
write_f32(test, f);
write_f16(test, f);
write_string(test, tetsuo);
test.index = 0;
a = read_u8(test);
a = read_u8(test);
b = read_u16(test);
c = read_u32(test);
d = read_u64(test);
e = read_s8(test);
f = read_f32(test);
uint8_t a_retrieved = read_u8(test);
a_retrieved = read_u8(test);
uint16_t b_retrieved = read_u16(test);
uint32_t c_retrieved = read_u32(test);
uint64_t d_retrieved = read_u64(test);
int8_t e_retrieved = read_s8(test);
float f_retrieved = read_f16(test);
rtt_f16(1.f);
rtt_f16(3.14159f);
rtt_f16(0.6666666666f);
rtt_f16(1.f / 3.f);
rtt_f16(99999.9f);
tetsuo = read_string(test);
std::cout << tetsuo << std::endl;