Crate lexical_parse_float

source ·
Expand description

Fast lexical string-to-float conversion routines.

The default implementations are highly optimized both for simple strings, as well as input with large numbers of digits. In order to keep performance optimal for simple strings, we avoid overly branching to minimize the number of branches (and therefore optimization checks). Most of the branches in the code are resolved at compile-time, and the resulting ASM as well as comprehensive benchmarks are monitored to ensure there are no regressions.

For simple floats, we use an optimized digit parser with multiple-digit optimizations (parsing 8 digits in 3 multiplication instructions), and then use machine floats to create an exact representation with high throughput. In more complex cases, we use the Eisel-Lemire algorithm, described in “Number Parsing at a Gigabyte per Second”, available online here. The Eisel-Lemire algorithm creates an extended representation using a 128-bit (or a fallback 192-bit representation) of the significant digits of the float, scaled to the proper exponent using pre-computed powers-of-5.

If the Eisel-Lemire algorithm is unable to unambiguously round the float, we fallback to using optimized, big-integer algorithms, which are described in Algorithm Approach below.

§Features

  • std - Use the standard library.
  • power-of-two - Add support for parsing power-of-two integer strings.
  • radix - Add support for strings of any radix.
  • format - Add support for parsing custom integer formats.
  • compact - Reduce code size at the cost of performance.

§Note

Only documented functionality is considered part of the public API: any of the modules, internal functions, or structs may change release-to-release without major or minor version changes. Use internal implementation details at your own risk.

lexical-parse-float mainly exists as an implementation detail for lexical-core, although its API is stable. If you would like to use a high-level API that writes to and parses from String and &str, respectively, please look at lexical instead. If you would like an API that supports multiple numeric conversions, please look at lexical-core instead.

§Machine Float-Only Algorithm

We also support an algorithm that uses only machine floats for the fast-path algorithm, however, this may be slower for floats with large exponents since it uses an iterative algorithm. A code sample using this is:

use lexical_parse_float::Options;
use lexical_parse_float::format::STANDARD;
use lexical_parse_float::parse::ParseFloat;

let options = Options::new();
let result = f64::fast_path_complete::<{ STANDARD }>(b"1.34000", &options);
assert_eq!(result, Ok(1.34000));

§Version Support

The minimum, standard, required version is 1.63.0, for const generic support. Older versions of lexical support older Rust versions.

§Safety

The primary use of unsafe code is in the big integer implementation, which for performance reasons requires unchecked indexing at certain points, where rust cannot elide the index check. The use of unsafe code can be found in the calculation of the hi bits, however, every invocation requires the buffer to be of sufficient length. The other major source is the implementation of methods such as push_unchecked, however, the safety invariants for each caller to create a safe API are documented and has similar safety guarantees to a regular vector. All other invocations of unsafe code are indexing a buffer where the index is proven to be within bounds within a few lines of code of the unsafe index.

§Design

Modules§

  • Public API for the number format packed struct.
  • Configuration options for parsing floats.

Structs§

Enums§

  • Error code during parsing, indicating failure type.

Traits§

Type Aliases§

  • A specialized Result type for lexical operations.