Add half precision floating point support to StreamPeer
Closes godotengine/godot-proposals#5983 Adds put/get methods to `StreamPeer` that handles half precision floating point values. Adds endode/decode half precision floating point to `marshalls`. Adds `get_half` and `store_half` to `FileAccess` Co-Authored-By: "Alfonso J. Ramos" <theraot@gmail.com>
This commit is contained in:
parent
ec6a1c0e79
commit
eb86670f94
15 changed files with 218 additions and 2 deletions
|
|
@ -39,7 +39,7 @@ namespace TestFileAccess {
|
|||
|
||||
TEST_CASE("[FileAccess] CSV read") {
|
||||
Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("testdata.csv"), FileAccess::READ);
|
||||
REQUIRE(!f.is_null());
|
||||
REQUIRE(f.is_valid());
|
||||
|
||||
Vector<String> header = f->get_csv_line(); // Default delimiter: ",".
|
||||
REQUIRE(header.size() == 4);
|
||||
|
|
@ -107,6 +107,98 @@ TEST_CASE("[FileAccess] Get as UTF-8 String") {
|
|||
CHECK(s_cr == "Hello darkness\rMy old friend\rI've come to talk\rWith you again\r");
|
||||
CHECK(s_cr_nocr == "Hello darknessMy old friendI've come to talkWith you again");
|
||||
}
|
||||
|
||||
TEST_CASE("[FileAccess] Get/Store floating point values") {
|
||||
// BigEndian Hex: 0x40490E56
|
||||
// LittleEndian Hex: 0x560E4940
|
||||
float value = 3.1415f;
|
||||
|
||||
SUBCASE("Little Endian") {
|
||||
const String file_path = TestUtils::get_data_path("floating_point_little_endian.bin");
|
||||
const String file_path_new = TestUtils::get_data_path("floating_point_little_endian_new.bin");
|
||||
|
||||
Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ);
|
||||
REQUIRE(f.is_valid());
|
||||
CHECK_EQ(f->get_float(), value);
|
||||
|
||||
Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE);
|
||||
REQUIRE(fw.is_valid());
|
||||
fw->store_float(value);
|
||||
fw->close();
|
||||
|
||||
CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path));
|
||||
|
||||
DirAccess::remove_file_or_error(file_path_new);
|
||||
}
|
||||
|
||||
SUBCASE("Big Endian") {
|
||||
const String file_path = TestUtils::get_data_path("floating_point_big_endian.bin");
|
||||
const String file_path_new = TestUtils::get_data_path("floating_point_big_endian_new.bin");
|
||||
|
||||
Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ);
|
||||
REQUIRE(f.is_valid());
|
||||
f->set_big_endian(true);
|
||||
CHECK_EQ(f->get_float(), value);
|
||||
|
||||
Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE);
|
||||
REQUIRE(fw.is_valid());
|
||||
fw->set_big_endian(true);
|
||||
fw->store_float(value);
|
||||
fw->close();
|
||||
|
||||
CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path));
|
||||
|
||||
DirAccess::remove_file_or_error(file_path_new);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("[FileAccess] Get/Store floating point half precision values") {
|
||||
// IEEE 754 half-precision binary floating-point format:
|
||||
// sign exponent (5 bits) fraction (10 bits)
|
||||
// 0 01101 0101010101
|
||||
// BigEndian Hex: 0x3555
|
||||
// LittleEndian Hex: 0x5535
|
||||
float value = 0.33325195f;
|
||||
|
||||
SUBCASE("Little Endian") {
|
||||
const String file_path = TestUtils::get_data_path("half_precision_floating_point_little_endian.bin");
|
||||
const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_little_endian_new.bin");
|
||||
|
||||
Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ);
|
||||
REQUIRE(f.is_valid());
|
||||
CHECK_EQ(f->get_half(), value);
|
||||
|
||||
Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE);
|
||||
REQUIRE(fw.is_valid());
|
||||
fw->store_half(value);
|
||||
fw->close();
|
||||
|
||||
CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path));
|
||||
|
||||
DirAccess::remove_file_or_error(file_path_new);
|
||||
}
|
||||
|
||||
SUBCASE("Big Endian") {
|
||||
const String file_path = TestUtils::get_data_path("half_precision_floating_point_big_endian.bin");
|
||||
const String file_path_new = TestUtils::get_data_path("half_precision_floating_point_big_endian_new.bin");
|
||||
|
||||
Ref<FileAccess> f = FileAccess::open(file_path, FileAccess::READ);
|
||||
REQUIRE(f.is_valid());
|
||||
f->set_big_endian(true);
|
||||
CHECK_EQ(f->get_half(), value);
|
||||
|
||||
Ref<FileAccess> fw = FileAccess::open(file_path_new, FileAccess::WRITE);
|
||||
REQUIRE(fw.is_valid());
|
||||
fw->set_big_endian(true);
|
||||
fw->store_half(value);
|
||||
fw->close();
|
||||
|
||||
CHECK_EQ(FileAccess::get_sha256(file_path_new), FileAccess::get_sha256(file_path));
|
||||
|
||||
DirAccess::remove_file_or_error(file_path_new);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TestFileAccess
|
||||
|
||||
#endif // TEST_FILE_ACCESS_H
|
||||
|
|
|
|||
|
|
@ -90,6 +90,20 @@ TEST_CASE("[Marshalls] Unsigned 64 bit integer decoding") {
|
|||
CHECK(decode_uint64(arr) == 0x0f123456789abcdef);
|
||||
}
|
||||
|
||||
TEST_CASE("[Marshalls] Floating point half precision encoding") {
|
||||
uint8_t arr[2];
|
||||
|
||||
// Decimal: 0.33325195
|
||||
// IEEE 754 half-precision binary floating-point format:
|
||||
// sign exponent (5 bits) fraction (10 bits)
|
||||
// 0 01101 0101010101
|
||||
// Hexadecimal: 0x3555
|
||||
unsigned int actual_size = encode_half(0.33325195f, arr);
|
||||
CHECK(actual_size == sizeof(uint16_t));
|
||||
CHECK(arr[0] == 0x55);
|
||||
CHECK(arr[1] == 0x35);
|
||||
}
|
||||
|
||||
TEST_CASE("[Marshalls] Floating point single precision encoding") {
|
||||
uint8_t arr[4];
|
||||
|
||||
|
|
@ -126,6 +140,13 @@ TEST_CASE("[Marshalls] Floating point double precision encoding") {
|
|||
CHECK(arr[7] == 0x3f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Marshalls] Floating point half precision decoding") {
|
||||
uint8_t arr[] = { 0x55, 0x35 };
|
||||
|
||||
// See floating point half precision encoding test case for details behind expected values.
|
||||
CHECK(decode_half(arr) == 0.33325195f);
|
||||
}
|
||||
|
||||
TEST_CASE("[Marshalls] Floating point single precision decoding") {
|
||||
uint8_t arr[] = { 0x00, 0x00, 0x20, 0x3e };
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,17 @@ TEST_CASE("[StreamPeer] Get and sets through StreamPeerBuffer") {
|
|||
CHECK_EQ(spb->get_u64(), value);
|
||||
}
|
||||
|
||||
SUBCASE("A half-precision float value") {
|
||||
float value = 3.1415927f;
|
||||
float expected = 3.14062f;
|
||||
|
||||
spb->clear();
|
||||
spb->put_half(value);
|
||||
spb->seek(0);
|
||||
|
||||
CHECK(spb->get_half() == doctest::Approx(expected));
|
||||
}
|
||||
|
||||
SUBCASE("A float value") {
|
||||
float value = 42.0f;
|
||||
|
||||
|
|
@ -255,6 +266,17 @@ TEST_CASE("[StreamPeer] Get and sets big endian through StreamPeerBuffer") {
|
|||
CHECK_EQ(spb->get_float(), value);
|
||||
}
|
||||
|
||||
SUBCASE("A half-precision float value") {
|
||||
float value = 3.1415927f;
|
||||
float expected = 3.14062f;
|
||||
|
||||
spb->clear();
|
||||
spb->put_half(value);
|
||||
spb->seek(0);
|
||||
|
||||
CHECK(spb->get_half() == doctest::Approx(expected));
|
||||
}
|
||||
|
||||
SUBCASE("A double value") {
|
||||
double value = 42.0;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue