lvext
Exact pure-Python codec for x87 80-bit extended-precision floats and LabVIEW's flattened EXT.
An x87 extended value is 10 bytes: a C long double on x86 Linux, and the layout of
LabVIEW's floatExt, the C type an EXT has when LabVIEW passes it to a library call on
Windows. When LabVIEW flattens an EXT (for example into a datalog file) it writes 16
bytes in the IEEE 754 binary128 layout instead. Python's float has 53 bits of
precision; an x87 value has 64, and so has every EXT LabVIEW flattens. lvext reads
and writes both layouts bit for bit, converts them to and from exact Fraction and
Decimal values, and rounds once, in any of the four IEEE modes, wherever precision
has to go.
Install
pip install lvext
Python 3.10 or newer, no dependencies.
Quick start
from decimal import Decimal
from fractions import Fraction
from lvext import Ext80, ExtKind, Rounding
# Every float fits exactly. Bytes come out big-endian unless you ask.
one = Ext80.from_float(1.0)
assert one.hex() == "3fff8000000000000000"
assert one.to_bytes("little") == bytes.fromhex("0000000000000080ff3f")
# Decode to the exact value: a Fraction, or a Decimal with every digit.
value = Ext80.from_hex("4000 c90f daa2 2168 c235")
assert value.kind is ExtKind.NORMAL
assert str(value.to_decimal()).startswith("3.14159265358979323851280895940618620443")
# Narrow to a float; the result says whether anything was lost.
assert value.narrow() == (3.141592653589793, False)
# Build from exact numbers, rounding once, in any of the four modes.
third = Ext80.from_fraction(Fraction(1, 3), Rounding.TOWARD_ZERO)
assert third.hex() == "3ffdaaaaaaaaaaaaaaaa"
assert Ext80.from_decimal(Decimal("0.1")).hex() == "3ffbcccccccccccccccd"
# LabVIEW's flattened EXT: 16 bytes, big-endian.
flat = Ext80.from_float(0.1).to_flattened()
assert flat.hex() == "3ffb999999999999a000000000000000"
assert Ext80.from_flattened(flat).to_float() == 0.1
The float-in, float-out helpers of the first release are still there:
from lvext import pack_ext, unpack_ext
assert pack_ext(-2.5) == bytes.fromhex("c000a000000000000000")
assert unpack_ext(pack_ext(-2.5)) == -2.5
Command line
$ lvext encode 1/3
3ffdaaaaaaaaaaaaaaab
$ lvext encode 0.1 --flattened
3ffb999999999999999a000000000000
$ lvext decode 3ffd8000000000000000
kind: normal
sign: +
exponent: 0x3ffd
mantissa: 0x8000000000000000
exact: 0.25
float: 0.25
float_hex: 3fd0000000000000
float_exact: yes
flattened: 3ffd0000000000000000000000000000
lvext --help lists every option; the guide
describes them.
How it is verified
- The x87 FPU itself. On Windows x86-64 the tests run the processor's own load and
store instructions through a small test-only
ctypeshelper and compare lvext with the hardware bit for bit, in all four rounding modes, over edge cases and thousands of random encodings. - LabVIEW 2026. 401 pairs of values that LabVIEW 2026 wrote itself, through three shipped VIs with EXT terminals: every double input flattens exactly as LabVIEW wrote it, and 230 products LabVIEW computed in EXT equal lvext's single rounding of the exact product (and differ from each of the other three modes). The guide lists the two corner cases where LabVIEW's bytes and lvext's differ, and why.
- Exact arithmetic. Golden vectors are exact rationals, rounding is checked against an exact oracle, and seeded fuzzing covers every reader and the command line.
Why
- Python's
structhas no 80-bit or 128-bit float format. numpy.longdoubleis the x87 type only where the platform's Clong doubleis (for example Linux on x86 with GCC); on Windows it is an 8-byte double.numpy-quaddtypeadds a binary128 dtype to NumPy as a compiled extension; it needs NumPy and does not read the 80-bit layout.
lvext does the bit arithmetic in pure Python, so the same bytes decode the same way on every platform, and it gives the exact value, not just the nearest float.
Documentation
- Guide: the formats, every public name, rounding, special values, LabVIEW details, errors and upgrading from 0.2.
- Changelog
License
MIT. See LICENSE.
Links
- Website: https://lianes8studio.com
- GitHub: https://github.com/JaviLianes8
- LinkedIn: https://www.linkedin.com/in/jlianes/
Metadata
Release files for lvext 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lvext-1.0.0.tar.gz | 56.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lvext-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 80.0 kB
Release files / lvext-1.0.0.tar.gz
| Download URL | lvext-1.0.0.tar.gz |
|---|---|
| Size | 56.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4db1f42d97ca5b6abbcec32d17f3780f92a8731b5ff75fc5d538f58bbffa4a43
|
|
BLAKE2b-256 checksum How to use checksums |
91eedbaef2445664cd4b06d6d382bd66258411ef12385f42702fd57e2c3cf443
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|
Release files / lvext-1.0.0-py3-none-any.whl
| Download URL | lvext-1.0.0-py3-none-any.whl |
|---|---|
| Size | 23.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6fd74e63678221006cd66de936754f9a9dc9810ebfdda0faf2ef72ff9524887f
|
|
BLAKE2b-256 checksum How to use checksums |
190ca9510a5fc2460eb95914f0f3fbeba7848a9fbc77ae26cb3233c8223c3572
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.2
|