Department of Computer Science, University of Southern Maine
For most of computing history, “a number” has meant one thing: an IEEE-754 floating-point value, the Float16, Float32, and Float64 formats baked into nearly every processor. A new open-source Julia package from the University of Southern Maine makes it easy to compute with the alternatives instead, and to see, in a live session, how they behave.
UniversalNumbers.jl, developed by James Quinlan and Mike Arciero of the Department of Computer Science, is a Julia wrapper for Stillwater’s Universal, a header-only C++ library of next-generation number systems. It puts Universal’s arithmetic behind a familiar Julia interface and, as of this release, is available in the Julia General registry. Any Julia user can install it with a single command, Pkg.add("UniversalNumbers"), and begin experimenting with more than thirty non-standard number formats drawn from nine different families.
Why look beyond standard floating point?
The way a computer represents numbers is not settled science. Standard floating point wastes bits in some situations and runs short of precision in others, and the tradeoffs it makes were fixed decades ago. Researchers have since proposed formats that promise more accuracy per bit, wider dynamic range, better reproducibility, and lower energy and memory cost. Among them are posits, takums, logarithmic number systems, and the compact 8-bit floats that now drive much of modern machine learning, where shrinking each number from 32 bits to 8 can make the difference between a model that fits on a chip and one that does not.
These are not idle ideas. They are the subject of active research, and evaluating their claims means running real algorithms in the candidate format and measuring what happens: Does a linear solver stay accurate? Where does precision break down? How does an iterative method respond to coarser rounding? Answering those questions has, until now, been harder than it should be.
Turning a C++ library into a Julia playground
Universal is the most complete reference implementation of these formats, comprehensive and well tested. But because it is header-only C++ built from template metaprogramming, using it directly has meant writing and compiling C++, wrangling template instantiations, and rebuilding the project every time you want to try a different format. For a numerical analyst sketching an algorithm, or a student trying to understand how rounding works, that is a steep wall.
UniversalNumbers.jl removes the wall. It wraps Universal’s arithmetic so the formats can be used directly at the Julia REPL, the interactive prompt where much scientific computing now happens. Each format behaves like an ordinary Julia number, which means switching from standard Float64 to a 16-bit posit is a one-line change rather than a recompilation:
using UniversalNumbers, LinearAlgebra
for T in (Float64, Posit{16,2}, Takum{16})
A = T[4 1; 1 3]
b = A * ones(T, 2)
x = A \ b
println(T, ": residual = ", norm(Float64.(A*x - b)))
end
The same algorithm runs unchanged across every format. Comparing three arithmetics on an ill-conditioned problem, an experiment that once required a C++ project, becomes a short script.
The package does not stop at the numbers themselves. It works with Julia’s sparse matrices and much of its linear algebra, including LU and QR factorizations, iterative solvers, and multigrid preconditioning. It also exposes a specialized feature of posit arithmetic called the quire, a wide accumulator that can sum a long list of products with a single rounding at the very end. In one test summing two thousand random terms, using the quire cut the error of a dot product by roughly 340 times compared to the ordinary rounded computation.
Built for teaching, too
One of the package’s design goals is education. Every value knows its exact format and can be pulled apart bit by bit with built-in inspection tools. An instructor can show a class, interactively, how a number is stored, where subnormals live, what happens at the edge of a format’s range, and how different systems signal “not a real number.” Concepts that are usually abstract become something a student can poke at in real time, without the friction of a compiled C++ environment.
That focus reflects where the work comes from. This is a project built at a teaching-focused department, by faculty who work with students, and its two motivating audiences, researchers prototyping algorithms and students learning how arithmetic behaves, are the same people it was designed to serve.
Open science, properly packaged
Getting the package into the Julia General registry was itself a piece of careful engineering. The underlying C++ arithmetic is compiled into a binary that ships automatically through Julia’s package infrastructure, so users get working arithmetic without ever installing a C++ compiler. Both the package and its binary component are registered through Yggdrasil, Julia’s community build system, and follow the same installation path as any other Julia package.
A paper describing the software has been prepared for submission to the Journal of Open Source Software (JOSS), a peer-reviewed venue for research software, continuing the department’s contributions to open, reproducible scientific computing.
Try it
UniversalNumbers.jl is free and open source under the MIT license. To install it,
start Julia and run:
using Pkg
Pkg.add("UniversalNumbers")
Source code, documentation, and worked examples are available on GitHub at
github.com/jamesquinlan/UniversalNumbers.jl.
UniversalNumbers.jl builds on the Stillwater Universal library by E. Theodore L. Omtzigt and contributors, and on the Takum reference implementation by Laslo Hunhold.
