# Rust 1.98.0 Lets the Compiler Reorder Your Floating-Point Math

Page: https://hirantha.me/blog/rust-1980-lets-the-compiler-reorder-your-floating-point-math
Published: 2026-08-25
Written by: hirantha.me Newsroom (AI-generated). An AI model wrote this from the sources listed below; how it is made: https://hirantha.me/about/newsroom
Topics: rust, programming-languages, compilers, performance, cargo

> Rust's new stable release adds opt-in algebraic float methods for faster math and a built-in replacement for the itoa crate.

## The eight-times-slower bug that started it

Rust 1.98.0, released August 20, 2026, addresses a performance gap that has irritated numerically-heavy Rust code for years: the compiler's historical refusal to reorder floating-point arithmetic. The issue traces back to a 2025 bug report showing that a straightforward dot-product loop, written the obvious way in Rust, ran up to eight times slower than the same loop in C++. The cause was not bad code - it was that Rust's floating-point operations follow the strict Institute of Electrical and Electronics Engineers (IEEE) 754 rounding rules by default, and the compiler will not reorder them even when reordering would be harmless for the task at hand, because doing so can change the result by a rounding error.

## What actually shipped

The headline addition is a family of algebraic methods on `f32` and `f64` covering addition, subtraction, multiplication, division and remainder. These are opt-in: existing code using the standard `+`, `-`, `*`, `/` operators keeps its current strict, order-preserving behavior. Calling the new algebraic methods instead tells the compiler it is free to reorder a chain of operations - for instance, evaluating `a + b + c + d` as `(a + b) + (c + d)` so the two partial sums can be computed independently, which in turn opens the door to auto-vectorization across a loop.

The tradeoff is explicit and documented: because reordering changes which rounding errors accumulate where, results from the algebraic methods can differ between runs, or between different optimization settings, even with identical inputs. This is the same class of tradeoff C and C++ developers already navigate with the `-ffast-math` compiler flag - Rust is not inventing a new risk, it is exposing an existing one as an explicit, function-level opt-in rather than a global build flag that silently changes every floating-point operation in a codebase. For numerical code where bit-for-bit reproducibility genuinely does not matter - large sums, physics simulations, machine learning kernels - that opt-in unlocks real speedups. For code where it does matter, such as financial calculations, nothing changes unless a developer deliberately reaches for the new methods.

## A smaller but more broadly useful change

The second notable addition targets a much more mundane bottleneck: converting integers to strings. Rust 1.98.0 stabilizes a `format_into` method paired with a new `NumBuffer` type, letting code write an integer's decimal representation into a pre-allocated buffer without the heap allocation that `to_string()` normally performs. Benchmarks accompanying the release show this built-in path performing on par with `itoa`, a third-party crate that has been a near-default dependency for performance-sensitive Rust code specifically because the standard library's own integer formatting was slower. For many projects, this closes a gap that previously required pulling in an external dependency just to format numbers efficiently in a hot loop.

## Smaller stabilizations worth knowing about

The release also formalizes a fix that had already shipped functionally in Rust 1.96.0: moving a dropped `ManuallyDrop<Box<_>>` is confirmed not to be undefined behavior, closing a gap between documented and actual compiler behavior. A handful of new standard library application programming interfaces (APIs) became stable, including `str::substr_range` and `[T]::subslice_range` for locating a substring or subslice's position within its parent, a `strip_circumfix` method, lossy UTF-16 (Unicode Transformation Format, 16-bit)-to-String conversion helpers, `Send` and `Sync` implementations for `std::process::CommandArgs`, radix-based parsing on the `NonZero` family of integer types, and several atomic-type mutation helpers. Separately, the derive-macro path at `{core,std}::derive` - which had been unintentionally accessible as stable since Rust 1.96 due to an oversight - is now officially and deliberately stabilized rather than quietly grandfathered in.

On the tooling side, Cargo, Rust's package manager and build tool, stabilized a config `include` key that lets a project's configuration file pull in and layer additional configuration files, making it easier to share common Cargo settings across a workspace or organization without duplicating them in every project. The release also carries a set of routine Clippy lint updates.

## Where this fits in Rust's trajectory

None of these changes are language syntax additions - they are the kind of incremental, opt-in performance and ergonomics work that has characterized recent Rust releases. The algebraic float methods in particular reflect a broader pattern in the language's evolution: giving developers explicit, scoped control over tradeoffs the compiler previously made unilaterally, rather than either forcing strict semantics everywhere or offering an all-or-nothing global flag.

## What this means in practice

Developers writing numerically intensive Rust code - graphics, simulations, machine learning kernels, anything currently reaching for Single Instruction, Multiple Data (SIMD) intrinsics or an external fast-math crate to get vectorized float performance - now have a standard-library path to try first, without needing to prove reproducibility does not matter for the whole crate, only for the specific operations that call the new methods. Anyone maintaining a dependency on `itoa` purely for performance may be able to drop it in favor of the new `format_into` method, though existing code has no obligation to change since nothing here is a breaking change to prior behavior.

## Sources

This article draws on the official Rust Blog release announcement, Phoronix's technical coverage of the algebraic float methods, and LinuxCompatible.org's summary of the Cargo and standard library changes.

## Questions

**Will Rust 1.98.0 change the output of my existing floating-point code?**
No. The algebraic reordering behavior is only available through new, explicitly-named methods; code using the standard +, -, *, / operators keeps its existing strict rounding behavior unchanged.

**Is this the same as C's -ffast-math flag?**
It addresses the same performance gap, but where -ffast-math applies globally to an entire compilation unit, Rust's algebraic methods are opt-in per operation, so a developer can enable reordering only where reproducibility genuinely does not matter.

**Do I still need the itoa crate?**
For most new code, no - the new format_into method with NumBuffer benchmarks on par with itoa for integer-to-string formatting, though existing projects have no obligation to remove the dependency.

**What caused Rust to add algebraic float methods now?**
A 2025 bug report showed that naive Rust dot-product code ran up to eight times slower than equivalent C++ because the compiler would not reorder floating-point operations for vectorization.

**How do I get Rust 1.98.0?**
Run rustup update if you already have Rust installed via rustup, which will pull the new stable release.

## Sources

- [Announcing Rust 1.98.0](https://blog.rust-lang.org/2026/08/20/Rust-1.98.0/), Rust Blog
- [Rust 1.98 Adds Algebraic Floating-Point Methods Akin To "-ffast-math"](https://www.phoronix.com/news/Rust-1.98-Released), Phoronix
- [Rust 1.98.0 Lands in Stable: Algebraic Floats, itoa Replacement, and Stability Fixes](https://www.linuxcompatible.org/story/rust-1980-lands-in-stable-algebraic-floats-itoa-replacement-and-stability-fixes/), LinuxCompatible.org
- [Release Rust 1.98.0](https://github.com/rust-lang/rust/releases/tag/1.98.0), GitHub (rust-lang/rust)
