lexical_parse_float/
lib.rs

1//! Fast lexical string-to-float conversion routines.
2//!
3//! The default implementations are highly optimized both for simple
4//! strings, as well as input with large numbers of digits. In order to
5//! keep performance optimal for simple strings, we avoid overly branching
6//! to minimize the number of branches (and therefore optimization checks).
7//! Most of the branches in the code are resolved at compile-time, and
8//! the resulting ASM as well as comprehensive benchmarks are monitored
9//! to ensure there are no regressions.
10//!
11//! For simple floats, we use an optimized digit parser with multiple-digit
12//! optimizations (parsing 8 digits in 3 multiplication instructions),
13//! and then use machine floats to create an exact representation with
14//! high throughput. In more complex cases, we use the Eisel-Lemire
15//! algorithm, described in "Number Parsing at a Gigabyte per Second",
16//! available online [here](https://arxiv.org/abs/2101.11408). The
17//! Eisel-Lemire algorithm creates an extended representation using a
18//! 128-bit (or a fallback 192-bit representation) of the significant
19//! digits of the float, scaled to the proper exponent using pre-computed
20//! powers-of-5.
21//!
22//! If the Eisel-Lemire algorithm is unable to unambiguously round the float,
23//! we fallback to using optimized, big-integer algorithms, which are
24//! described in [Algorithm Approach](#algorithm-approach) below.
25//!
26//! # Features
27//!
28//! * `std` - Use the standard library.
29//! * `power-of-two` - Add support for parsing power-of-two integer strings.
30//! * `radix` - Add support for strings of any radix.
31//! * `format` - Add support for parsing custom integer formats.
32//! * `compact` - Reduce code size at the cost of performance.
33//! * `safe` - Ensure only memory-safe indexing is used.
34//! * `nightly` - Enable assembly instructions to control FPU rounding modes.
35//!
36//! `safe` has a fairly minimal impact, since all parsers are memory-safe
37//! by default except where unsafe functionality can trivially be proven
38//! correct.
39//!
40//! # Note
41//!
42//! Only documented functionality is considered part of the public API:
43//! any of the modules, internal functions, or structs may change
44//! release-to-release without major or minor version changes. Use
45//! internal implementation details at your own risk.
46//!
47//! lexical-parse-float mainly exists as an implementation detail for
48//! lexical-core, although its API is stable. If you would like to use
49//! a high-level API that writes to and parses from `String` and `&str`,
50//! respectively, please look at [lexical](https://crates.io/crates/lexical)
51//! instead. If you would like an API that supports multiple numeric
52//! conversions, please look at [lexical-core](https://crates.io/crates/lexical-core)
53//! instead.
54//!
55//! # Machine Float-Only Algorithm
56//!
57//! We also support an algorithm that uses only machine floats for the
58//! fast-path algorithm, however, this may be slower for floats with large
59//! exponents since it uses an iterative algorithm. A code sample
60//! using this is:
61//!
62//! ```rust
63//! use lexical_parse_float::Options;
64//! use lexical_parse_float::format::STANDARD;
65//! use lexical_parse_float::parse::ParseFloat;
66//!
67//! let options = Options::new();
68//! let result = f64::fast_path_complete::<{ STANDARD }>(b"1.34000", &options);
69//! assert_eq!(result, Ok(1.34000));
70//! ```
71//!
72//! # Version Support
73//!
74//! The minimum, standard, required version is 1.51.0, for const generic
75//! support. Older versions of lexical support older Rust versions.
76//!
77//! # Design
78//!
79//! - [Algorithm Approach](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Algorithm.md)
80//! - [Benchmarks](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/Benchmarks.md)
81//! - [Big Integer Implementation](https://github.com/Alexhuszagh/rust-lexical/blob/main/lexical-parse-float/docs/BigInteger.md)
82
83// Inline ASM was stabilized in 1.59.0.
84// FIXME: Remove when the MSRV for Rustc >= 1.59.0.
85#![allow(stable_features)]
86// We want to have the same safety guarantees as Rust core,
87// so we allow unused unsafe to clearly document safety guarantees.
88#![allow(unused_unsafe)]
89#![cfg_attr(feature = "lint", warn(unsafe_op_in_unsafe_fn))]
90#![cfg_attr(not(feature = "std"), no_std)]
91#![cfg_attr(feature = "nightly", feature(asm))]
92
93#[macro_use]
94mod index;
95#[macro_use]
96pub mod shared;
97
98pub mod bellerophon;
99pub mod bigint;
100pub mod binary;
101pub mod float;
102pub mod fpu;
103pub mod lemire;
104pub mod libm;
105pub mod limits;
106pub mod mask;
107pub mod number;
108pub mod options;
109pub mod parse;
110pub mod slow;
111pub mod table;
112
113mod api;
114mod table_bellerophon_decimal;
115mod table_bellerophon_radix;
116mod table_binary;
117mod table_decimal;
118mod table_large;
119mod table_lemire;
120mod table_radix;
121mod table_small;
122
123// Re-exports
124pub use self::api::{FromLexical, FromLexicalWithOptions};
125#[doc(inline)]
126pub use self::options::{Options, OptionsBuilder};
127#[cfg(feature = "f16")]
128pub use lexical_util::bf16::bf16;
129pub use lexical_util::error::Error;
130#[cfg(feature = "f16")]
131pub use lexical_util::f16::f16;
132pub use lexical_util::format::{self, NumberFormatBuilder};
133pub use lexical_util::options::ParseOptions;
134pub use lexical_util::result::Result;