Index: net/quic/quic_data_writer.cc |
diff --git a/net/quic/quic_data_writer.cc b/net/quic/quic_data_writer.cc |
index 61e729223652d3f620878a8f7ec64dbf110ffeda..65ce7bee998d5d54e21a925de0a2691924e78ac4 100644 |
--- a/net/quic/quic_data_writer.cc |
+++ b/net/quic/quic_data_writer.cc |
@@ -56,6 +56,45 @@ bool QuicDataWriter::WriteUInt64(uint64 value) { |
return WriteBytes(&value, sizeof(value)); |
} |
+bool QuicDataWriter::WriteUFloat16(uint64 value) { |
+ uint16 result; |
+ if (value < (GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits)) { |
+ // Fast path: either the value is denormalized, or has exponent zero. |
+ // Both cases are represented by the value itself. |
+ result = value; |
+ } else if (value >= kUFloat16MaxValue) { |
+ // Value is out of range; clamp it to the maximum representable. |
+ result = numeric_limits<uint16>::max(); |
+ } else { |
+ // The highest bit is between position 13 and 42 (zero-based), which |
+ // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10, |
+ // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11 |
+ // and count the shifts. |
+ uint16 exponent = 0; |
+ for (uint16 offset = 16; offset > 0; offset /= 2) { |
+ // Right-shift the value until the highest bit is in position 11. |
+ // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30), |
+ // shift if the bit is at or above 11 + offset. |
+ if (value >= (GG_UINT64_C(1) << (kUFloat16MantissaBits + offset))) { |
+ exponent += offset; |
+ value >>= offset; |
+ } |
+ } |
+ |
+ DCHECK_GE(exponent, 1); |
+ DCHECK_LE(exponent, kUFloat16MaxExponent); |
+ DCHECK_GE(value, GG_UINT64_C(1) << kUFloat16MantissaBits); |
+ DCHECK_LT(value, GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits); |
+ |
+ // Hidden bit (position 11) is set. We should remove it and increment the |
+ // exponent. Equivalently, we just add it to the exponent. |
+ // This hides the bit. |
+ result = value + (exponent << kUFloat16MantissaBits); |
+ } |
+ |
+ return WriteBytes(&result, sizeof(result)); |
+} |
+ |
bool QuicDataWriter::WriteStringPiece16(StringPiece val) { |
if (val.length() > numeric_limits<uint16>::max()) { |
return false; |