HN user

vitaut

1,361 karma

Carbon-based open sourcerer, code necromancer and a former alien. Author of C++20 std::format and http://github.com/fmtlib/fmt. Opinions are not mine.

Posts82
Comments132
View on HN
maurycyz.com 4d ago

Regressive JPEGs

vitaut
723pts69
discourse.llvm.org 2mo ago

Open Access to Standards Documents

vitaut
3pts1
github.com 5mo ago

Astrological CPU Scheduler

vitaut
4pts0
dougallj.wordpress.com 5mo ago

Bitwise conversion of doubles using only FP multiplication and addition (2020)

vitaut
57pts6
www.npopov.com 6mo ago

LLVM: The bad parts

vitaut
389pts77
queue.acm.org 8mo ago

Hardening the C++ Standard Library at massive scale

vitaut
1pts0
cppalliance.org 8mo ago

Making the Clang AST Leaner and Faster

vitaut
50pts9
www.youtube.com 10mo ago

C++ Memory Safety in WebKit [video]

vitaut
3pts0
blog.jetbrains.com 10mo ago

CLion Introduces Constexpr Debugger

vitaut
3pts0
discourse.llvm.org 11mo ago

Hardening mode for the compiler

vitaut
158pts54
probablydance.com 1y ago

Revisiting Knuth's "Premature Optimization" Paper

vitaut
3pts0
xania.org 1y ago

How Compiler Explorer Works in 2025

vitaut
232pts46
www.youtube.com 1y ago

Where did <random> go wrong? [video]

vitaut
1pts0
isocpp.org 1y ago

Results summary: 2025 Annual C++ Developer Survey "Lite" [pdf]

vitaut
2pts0
20k.github.io 1y ago

Simulating fast binary black hole collisions on the GPU

vitaut
1pts0
www.circle-lang.org 1y ago

Building Bridges to C++

vitaut
5pts0
vitaut.net 1y ago

Double to string conversion in 150 lines of code

vitaut
3pts0
fmt.dev 2y ago

A Modern Formatting Library

vitaut
3pts0
blog.sigplan.org 2y ago

A DSL for Implementing Math Functions

vitaut
86pts13
fwsgonzo.medium.com 2y ago

An Introduction to Low-Latency Scripting with Libriscv

vitaut
2pts0
www.qualys.com 2y ago

Out-of-bounds read and write in glibc's qsort()

vitaut
4pts1
mdpi-res.com 2y ago

How Close Is Existing C/C++ Code to a Safe Subset? [pdf]

vitaut
1pts0
github.com 2y ago

Bad Apple in CMake

vitaut
2pts0
vitaut.net 2y ago

std::print in C++23

vitaut
2pts0
www.open-std.org 2y ago

WG21, a.k.a. C++ Standard Committee, December 2023 Mailing

vitaut
1pts0
www.zverovich.net 3y ago

Printing double a.k.a. the most difficult problem in computer sciences

vitaut
4pts0
github.com 3y ago

A lightweight (~5000 LOC) Python interpreter for game engines

vitaut
106pts76
brevzin.github.io 3y ago

Rust vs. C++ Formatting

vitaut
163pts104
www.youtube.com 4y ago

James Web Space Telescope runs on C++ code

vitaut
1pts1
github.com 4y ago

Round Float.pi down so that it's in [0,π]

vitaut
2pts0

Interviewer: Mr. Musk, I understand the wheels fell off the Cybertruck.

Musk: Well, that’s not very typical. Most vehicles are designed so the wheels don’t fall off.

Interviewer: But these ones did.

Musk: Well obviously. That’s why we recalled them. But wheel retention remains a very high priority at Tesla.

Interviewer: What caused it?

Musk: A minor component interaction that generated maximum freedom.

Interviewer: Freedom?

Musk: For the wheel.

The binary bloat is also caused by unnecessary inlining and the linker eliminates most of it (but it's still annoying e.g. for godbolt). {fmt} supports a superset of std::format and std::print features including localization. stringstream's bloat is unrelated and mostly caused by large per-call binary code from concatenation-based API.

std::print author here. Indeed, std::print shouldn't be expensive to compile, it's just a thin wrapper around a single type-erased function. The only reason why it is expensive in libstdc++ is that the type-erased function is inlined which goes against the proposed design but unfortunately can't be enforced via the standard wording and remains a Quality of Implementation (QoI) issue.

Fortunately, libstdc++ is fixing this: https://gcc.gnu.org/pipermail/gcc-patches/2026-March/710275..... There is still more work to optimize the includes but it's a good start.

If you compress the table (see my earlier comment) and use plain Schubfach then you can get really small binary size and decent perf. IIRC Dragonbox with the compressed table was ~30% slower which is a reasonable price to pay and still faster than most algorithms including Ryu.

Somewhat notable is that `char8_t` is banned with very reasonable motivation that applies to most codebases:

Use char and unprefixed character literals. Non-UTF-8 encodings are rare enough in Chromium that the value of distinguishing them at the type level is low, and char8_t* is not interconvertible with char* (what ~all Chromium, STL, and platform-specific APIs use), so using u8 prefixes would obligate us to insert casts everywhere. If you want to declare at a type level that a block of data is string-like and not an arbitrary binary blob, prefer std::string[_view] over char*.

The shortest double-to-string algorithm is basically Schubfach or, rather, it's variation Tejú Jaguá with digit output from Dragonbox. Schubfach is a beautiful algorithm: I implemented and wrote about it in https://vitaut.net/posts/2025/smallest-dtoa/. However, in terms of performance you can do much better nowadays. For example, https://github.com/vitaut/zmij does 1 instead of 2-3 costly 128x64-bit multiplications in the common case and has much more efficient digit output.

Please note that there is some error in your port:

Error: roundtrip fail 4.9406564584124654e-324 -> '5.e-309' -> 4.9999999999999995e-309

Error: roundtrip fail 6.6302941479442929e-310 -> '6.6302941479443e-309' -> 6.6302941479442979e-309

Error: roundtrip fail -1.9153028533493997e-310 -> '-1.9153028533494e-309' -> -1.9153028533493997e-309

Error: roundtrip fail -2.5783653320086361e-312 -> '-2.57836533201e-309' -> -2.5783653320099997e-309

Cool, please share once it is complete.

C++ also provides countl_zero: https://en.cppreference.com/w/cpp/numeric/countl_zero.html. We currently use our own for maximum portability.

I considered computing the table at compile time (you can do it in C++ using constexpr) but decided against it not to add compile-time overhead, however small. The table never changes so I'd rather not make users pay for recomputing it every time.

Unlike formatting, correct parsing involves high precision arithmetic.

Formatting also requires high precision arithmetic unless you disallow user-specified precision. That's why {fmt} still has an implementation of Dragon4 as a fallback for such silly cases.

This is possible and the trailing zeros are indeed removed (with the exponent adjusted accordingly) in the write function. The post mentions removing trailing zeros without going into details but it's a pretty interesting topic and was recently changed to use lzcnt/bsr instead of a lookup table.