mirror of
https://github.com/nlohmann/json
synced 2024-11-27 14:20:07 +00:00
✨ CBOR support for half-precision floats
This commit is contained in:
parent
17c9b17a7e
commit
b7e0c12966
25
src/json.hpp
25
src/json.hpp
@ -34,7 +34,7 @@ SOFTWARE.
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <ciso646> // and, not, or
|
||||
#include <cmath> // isfinite, signbit
|
||||
#include <cmath> // isfinite, ldexp, signbit
|
||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||
#include <cstdint> // int64_t, uint64_t
|
||||
#include <cstdlib> // strtod, strtof, strtold, strtoul
|
||||
@ -7169,6 +7169,29 @@ class basic_json
|
||||
{
|
||||
return value_t::null;
|
||||
}
|
||||
else if (v[current_idx] == 0xf9) // Half-Precision Float
|
||||
{
|
||||
idx += 2; // skip two content bytes
|
||||
|
||||
// code from RFC 7049, Appendix D
|
||||
const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
|
||||
const int exp = (half >> 10) & 0x1f;
|
||||
const int mant = half & 0x3ff;
|
||||
double val;
|
||||
if (exp == 0)
|
||||
{
|
||||
val = std::ldexp(mant, -24);
|
||||
}
|
||||
else if (exp != 31)
|
||||
{
|
||||
val = std::ldexp(mant + 1024, exp - 25);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = mant == 0 ? INFINITY : NAN;
|
||||
}
|
||||
return half & 0x8000 ? -val : val;
|
||||
}
|
||||
else if (v[current_idx] == 0xfa) // Single-Precision Float
|
||||
{
|
||||
// copy bytes in reverse order into the float variable
|
||||
|
@ -34,7 +34,7 @@ SOFTWARE.
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <ciso646> // and, not, or
|
||||
#include <cmath> // isfinite, signbit
|
||||
#include <cmath> // isfinite, ldexp, signbit
|
||||
#include <cstddef> // nullptr_t, ptrdiff_t, size_t
|
||||
#include <cstdint> // int64_t, uint64_t
|
||||
#include <cstdlib> // strtod, strtof, strtold, strtoul
|
||||
@ -7169,6 +7169,35 @@ class basic_json
|
||||
{
|
||||
return value_t::null;
|
||||
}
|
||||
else if (v[current_idx] == 0xf9) // Half-Precision Float
|
||||
{
|
||||
idx += 2; // skip two content bytes
|
||||
|
||||
// code from RFC 7049, Appendix D, Figure 3:
|
||||
// As half-precision floating-point numbers were only added to IEEE
|
||||
// 754 in 2008, today's programming platforms often still only have
|
||||
// limited support for them. It is very easy to include at least
|
||||
// decoding support for them even without such support. An example
|
||||
// of a small decoder for half-precision floating-point numbers in
|
||||
// the C language is shown in Figure 3.
|
||||
const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
|
||||
const int exp = (half >> 10) & 0x1f;
|
||||
const int mant = half & 0x3ff;
|
||||
double val;
|
||||
if (exp == 0)
|
||||
{
|
||||
val = std::ldexp(mant, -24);
|
||||
}
|
||||
else if (exp != 31)
|
||||
{
|
||||
val = std::ldexp(mant + 1024, exp - 25);
|
||||
}
|
||||
else
|
||||
{
|
||||
val = mant == 0 ? INFINITY : NAN;
|
||||
}
|
||||
return half & 0x8000 ? -val : val;
|
||||
}
|
||||
else if (v[current_idx] == 0xfa) // Single-Precision Float
|
||||
{
|
||||
// copy bytes in reverse order into the float variable
|
||||
|
@ -1102,26 +1102,26 @@ TEST_CASE("examples from RFC 7049 Appendix A")
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("0.0")) == std::vector<uint8_t>({0xf9, 0x00, 0x00}));
|
||||
//CHECK(json::parse("0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00})));
|
||||
CHECK(json::parse("0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x00, 0x00})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("-0.0")) == std::vector<uint8_t>({0xf9, 0x80, 0x00}));
|
||||
//CHECK(json::parse("-0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00})));
|
||||
CHECK(json::parse("-0.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x80, 0x00})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("1.0")) == std::vector<uint8_t>({0xf9, 0x3c, 0x00}));
|
||||
//CHECK(json::parse("1.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00})));
|
||||
CHECK(json::parse("1.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3c, 0x00})));
|
||||
|
||||
CHECK(json::to_cbor(json::parse("1.1")) == std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a}));
|
||||
CHECK(json::parse("1.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0x3f, 0xf1, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("1.5")) == std::vector<uint8_t>({0xf9, 0x3e, 0x00}));
|
||||
//CHECK(json::parse("1.5") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3e, 0x00})));
|
||||
CHECK(json::parse("1.5") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x3e, 0x00})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("65504.0")) == std::vector<uint8_t>({0xf9, 0x7b, 0xff}));
|
||||
//CHECK(json::parse("65504.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff})));
|
||||
CHECK(json::parse("65504.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0x7b, 0xff})));
|
||||
|
||||
//CHECK(json::to_cbor(json::parse("100000.0")) == std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00}));
|
||||
CHECK(json::parse("100000.0") == json::from_cbor(std::vector<uint8_t>({0xfa, 0x47, 0xc3, 0x50, 0x00})));
|
||||
@ -1134,15 +1134,15 @@ TEST_CASE("examples from RFC 7049 Appendix A")
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("5.960464477539063e-8")) == std::vector<uint8_t>({0xf9, 0x00, 0x01}));
|
||||
//CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("0.00006103515625")) == std::vector<uint8_t>({0xf9, 0x04, 0x00}));
|
||||
//CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
|
||||
// half-precision float
|
||||
//CHECK(json::to_cbor(json::parse("-4.0")) == std::vector<uint8_t>({0xf9, 0xc4, 0x00}));
|
||||
//CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
CHECK(json::parse("-4.0") == json::from_cbor(std::vector<uint8_t>({0xf9, 0xc4, 0x00})));
|
||||
|
||||
CHECK(json::to_cbor(json::parse("-4.1")) == std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}));
|
||||
CHECK(json::parse("-4.1") == json::from_cbor(std::vector<uint8_t>({0xfb, 0xc0, 0x10, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66})));
|
||||
|
Loading…
Reference in New Issue
Block a user