zerodds-float128

IEEE 754 binary128 in software: the sixteen bytes CDR gives long double, as a value type with exact conversions, IEEE comparison, and round-tripping decimal.

use zerodds_float128::Float128;

// Sixteen bytes off the wire and sixteen back, unchanged.
let value = Float128::from_be_bytes(bytes);
assert_eq!(value.to_be_bytes(), bytes);

// A value a double can hold converts; one it cannot is refused by name.
let narrow: f64 = value.to_f64()?;

Why it exists

CORBA 3.3 part 2 §9.3.1.3 gives long double one sign bit, a fifteen-bit exponent and a 112-bit fraction, and DDS-XTypes 1.3 Table 31 names the result: quadruple precision, sixteen bytes, aligned to eight. Rust has no stable f128, so this project used to write a double and eight zero bytes for it — the right length, the wrong value, and no error. Carrying the value needs no arithmetic, only bit manipulation and long division.

What it does

  • Lossless sixteen-byte round trip in both byte orders. CORBA Figure 9.2 reverses the whole sixteen bytes between orders, not two halves, and that is what RTI Connext was measured doing.
  • Exact conversion from f32, f64 and the integers, and back with the inexact cases returned as an Inexact carrying the rounded value — never rounded in silence.
  • IEEE comparison, plus total_cmp for a @key member and a sorted expectation, where a None for NaN is not an answer.
  • Decimal in and out, correctly rounded against the exact value, so a JSON value file can carry one. to_shortest_decimal writes the fewest digits that read back; to_exact_decimal writes all of them.
  • The x87 80-bit extended format, in both directions, because Fast DDS and OpenDDS put that on the wire on x86-64 and a reader that only knows the conformant form cannot read the field.

What it does not do

Arithmetic. No Add, no Mul, no sqrt. Nothing on the wire path needs them and a half-correct one is worse than none; docs/float128-column.md §6 says what adding them would take and how it would be checked.

The oracle

tests/oracle/ holds values run through GCC's __float128, compared in both directions: their printer against this crate's parser, and their parser against this crate's printer. A crate that implements a format cannot be its own second opinion.

Position

zerodds-float128

IEEE 754 binary128 in Software: die sechzehn Bytes, die CDR einem long double gibt, als Werttyp mit exakten Umwandlungen, IEEE-Vergleich und Dezimaldarstellung, die sich verlustfrei zurücklesen lässt.

use zerodds_float128::Float128;

// Sixteen bytes off the wire and sixteen back, unchanged.
let value = Float128::from_be_bytes(bytes);
assert_eq!(value.to_be_bytes(), bytes);

// A value a double can hold converts; one it cannot is refused by name.
let narrow: f64 = value.to_f64()?;

Warum es sie gibt

CORBA 3.3 Teil 2 §9.3.1.3 gibt long double ein Vorzeichenbit, einen Exponenten von fünfzehn Bit und eine Mantisse von 112 Bit, und DDS-XTypes 1.3 Tabelle 31 benennt das Ergebnis: vierfache Genauigkeit, sechzehn Bytes, auf acht ausgerichtet. Rust hat kein stabiles f128; dieses Projekt schrieb deshalb früher ein double und acht Nullbytes — die richtige Länge, der falsche Wert und kein Fehler. Den Wert zu transportieren braucht keine Arithmetik, nur Bitmanipulation und schriftliche Division.

Was sie tut

  • Verlustfreier Roundtrip der sechzehn Bytes in beiden Bytereihenfolgen. CORBA Abbildung 9.2 kehrt beim Wechsel der Reihenfolge alle sechzehn Bytes um, nicht zwei Hälften, und so verhielt sich RTI Connext in der Messung.
  • Exakte Umwandlung aus f32, f64 und den Ganzzahltypen und zurück; ungenaue Fälle kommen als Inexact mit dem gerundeten Wert zurück — nie stillschweigend gerundet.
  • IEEE-Vergleich, dazu total_cmp für einen @key-Member und eine sortierte Erwartung, wo ein None für NaN keine Antwort ist.
  • Dezimalzahlen hinein und heraus, korrekt gerundet gegen den exakten Wert, damit eine JSON-Wertedatei einen solchen Wert tragen kann. to_shortest_decimal schreibt die wenigsten Ziffern, die sich zurücklesen lassen; to_exact_decimal schreibt alle.
  • Das erweiterte 80-Bit-Format von x87, in beide Richtungen, weil Fast DDS und OpenDDS es auf x86-64 auf die Leitung legen und ein Reader, der nur die konforme Form kennt, das Feld nicht lesen kann.

Was sie nicht tut

Arithmetik. Kein Add, kein Mul, kein sqrt. Nichts auf dem Weg zur Leitung braucht sie, und eine halb richtige ist schlechter als keine; docs/float128-column.md §6 beschreibt, was es bräuchte, sie hinzuzufügen, und wie es geprüft würde.

Das Orakel

tests/oracle/ enthält Werte, die durch __float128 von GCC gelaufen sind, verglichen in beide Richtungen: deren Ausgabe gegen den Parser dieser Crate und deren Parser gegen die Ausgabe dieser Crate. Eine Crate, die ein Format implementiert, kann nicht ihre eigene zweite Meinung sein.

Stellung