Skip to content

feat(cpp): add float16 to c++#3487

Open
UninspiredCarrot wants to merge 22 commits intoapache:mainfrom
UninspiredCarrot:float16-clean
Open

feat(cpp): add float16 to c++#3487
UninspiredCarrot wants to merge 22 commits intoapache:mainfrom
UninspiredCarrot:float16-clean

Conversation

@UninspiredCarrot
Copy link

@UninspiredCarrot UninspiredCarrot commented Mar 16, 2026

Why?

Implement float16_t (IEEE 754 binary16 / half-precision) as a primitive type in the C++ runtime, as required by issue #3208. No C++ standard type represents float16, so the framework needs its own strong type with correct IEEE 754 semantics and serialiser integration.

What does this PR do?

cpp/fory/util/float16.h / float16.cc — new fory::float16_t strong type:

  • Trivial, standard-layout, exactly 2 bytes; internal storage is uint16_t bits accessed only via to_bits()/from_bits()
  • from_float / to_float — IEEE 754 compliant conversion with round-to-nearest ties-to-even, correct handling of ±0, ±Inf, NaN (payload preserved, signaling→quiet), subnormals, overflow→Inf, underflow→subnormal/±0
  • Classification: is_nan, is_inf (two overloads), is_zero, signbit, is_subnormal, is_normal, is_finite
  • Arithmetic: add, sub, mul, div, neg, abs; optional math: sqrt, min, max, copysign, floor, ceil, trunc, round, round_to_even; compound assignment and binary operator overloads
  • Comparisons: equal, less, less_eq, greater, greater_eq, compare (NaN unordered, +0 == −0); comparison operator overloads (==, !=, <, <=, >, >=)

cpp/fory/serialization/struct_serializer.h — serializer integration:

  • Serializer<float16_t> specialization wired to TypeId::FLOAT16 (type ID 17)

cpp/fory/util/float16_test.cc — exhaustive tests (1300+ lines, 61 test cases):

  • Stress-tests all 65 536 bit patterns for round-trip correctness
  • Ties-to-even rounding, subnormal gradual underflow, overflow→Inf, NaN payload preservation
  • Buffer wire-format goldens (little-endian), serializer round-trips (scalar, vector, map, optional), type ID check
  • Full comparison test suite including NaN unordered and ±0 equality edge cases

Related issues

AI Contribution Checklist

  • Substantial AI assistance was used in this PR: yes
  • If yes, I included a completed AI Contribution Checklist in this PR description and the required AI Usage Disclosure.
    • Substantial AI assistance was used in this PR: yes
    • If yes, I included a completed AI Contribution Checklist in this PR description and the required AI Usage Disclosure.
    • If yes, I can explain and defend all important changes without AI help.
    • If yes, I reviewed AI-assisted code changes line by line before submission.
    • If yes, I ran adequate human verification and recorded evidence (checks run locally or in CI, pass/fail summary, and confirmation I reviewed results).
    • If yes, I added/updated tests and specs where required.
    • If yes, I validated protocol/performance impacts with evidence when applicable.
    • If yes, I verified licensing and provenance compliance.

AI Usage Disclosure

  • substantial_ai_assistance: yes
  • scope: tests
  • affected_files_or_subsystems: cpp/fory/util/float16_test.cc
  • human_verification: bazel test //cpp/fory/util:float16_test — 61/61 passed locally; contributor reviewed all diffs line by line
  • performance_verification: N/A
  • provenance_license_confirmation: Apache-2.0-compatible provenance confirmed; no incompatible third-party code introduced

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
  • Does this PR introduce any binary protocol compatibility change?

@UninspiredCarrot UninspiredCarrot changed the title Float16 clean feat(cpp): add float16 to c++ Mar 16, 2026
@UninspiredCarrot UninspiredCarrot force-pushed the float16-clean branch 2 times, most recently from 0e2da14 to 7f948b9 Compare March 17, 2026 00:59
@UninspiredCarrot UninspiredCarrot marked this pull request as ready for review March 17, 2026 01:08
@UninspiredCarrot UninspiredCarrot marked this pull request as ready for review March 17, 2026 15:55

// A 16-bit floating point representation with 1 sign bit, 5 exponent bits, and
// 10 mantissa bits.
struct float16_t {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a std::hash<fory::float16_t> specialization alongside the comparison operators. Right now std::unordered_map<float16_t, ...> / std::unordered_set<float16_t> do not compile at all; a minimal local compile probe fails immediately because the default std::hash is deleted.

}
}

TEST(Float16SerializerTest, VectorRoundTrip) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This round-trip only proves C++ can serialize and deserialize the same struct locally. It does not catch the wire-format regression here: std::vector<float16_t> still falls through the non-arithmetic vector serializer and emits LIST, because std::is_arithmetic_v<float16_t> is false. Please either wire float16_t into the typed-array path or assert here that the emitted type id is FLOAT16_ARRAY.

EXPECT_EQ(deser.value(), original);
}

TEST(Float16SerializerTest, EmptyVectorRoundTrip) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a fixed-size array case in this serializer test block as well. std::array<float16_t, N> is still unsupported today, because the generic primitive-array serializer is gated on std::is_arithmetic_v<T> and there is no explicit float16_t specialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[C++] add float16 to c++

2 participants