Mercury — Arbitrary-Precision Mathematics, From the Inside Out
Mercury is a native C library for arbitrary-precision floating-point arithmetic, with a .NET interface named UltraNumber. It is also an invitation to look inside the arithmetic: how a number is represented, how its pieces move, and how familiar operations emerge from those rules.
Choose a precision, follow the algorithms, and see how machine-level representation connects to addition, multiplication, division, roots, powers, and logarithms.

A closer look at high-precision arithmetic
Ordinary floating-point types offer a fixed amount of precision. Arbitrary-precision arithmetic lets a program work with a chosen number of significant binary words instead. That makes it possible to explore calculations whose precision needs exceed the built-in types—and to study the algorithms that make those calculations work.
Mercury makes that process unusually visible. Its native representation and hexadecimal strings expose the relationship between mathematical values and machine-sized pieces. The project pairs a practical arithmetic engine with an educational series that follows the implementation from low-level operations toward powers and logarithms.
How Mercury represents numbers
A Mercury value is stored in a sequence of 32-bit words. The first word contains the sign flag, the next holds a signed exponent measured in base-2^32 word places, and the remaining words hold the mantissa. Each 32-bit limb corresponds to eight hexadecimal digits, so hexadecimal output gives a direct view of the stored precision.
At a glance: sign + word exponent + configurable mantissa limbs
Precision counts the 32-bit mantissa words. For example, 16 words provide 512 bits of mantissa storage; 64 words provide 2048 bits. The canonical reference includes additional precision examples and the exact buffer layout.
Arithmetic routines use a caller-supplied scratch stack for temporary work. The caller allocates the workspace, each operation takes and releases temporary regions in last-in, first-out order, and each thread needs its own stack. This makes temporary memory use explicit; the application must provide a stack large enough for the work it requests.
Explore the algorithms
These articles turn the implementation into a reading path. Start with the overview, then follow how each new operation builds on the previous one.
Mercury has landed
Meet the native engine, its hexadecimal view of numbers, and the role of the .NET wrapper.
Addition, subtraction, and aliasing
See how sign handling is separated from magnitude arithmetic, and why output can safely reuse an input buffer.
Carrying in base 2^32
Connect the familiar carry from grade-school addition to a 32-bit limb and a 64-bit register.
Multiplication and geometric scaling
Follow the multiplicative tier and how the places of two multiword values combine.
Division: preparing the table
Explore how precomputed multiples help turn a large division into structured lookup and subtraction work.
Division: sliding windows
See how the prepared table moves across the dividend as the quotient is constructed.
Squaring, roots, and halving
Explore the symmetry between squaring and square roots, and why successive roots halve an exponent step.
Powers by binary squaring
Learn how exponent bits avoid a long chain of repeated multiplication and how fractional powers fit the same picture.
Roots and logarithms as inverses
Follow root extraction back through powers, then watch logarithms construct the missing exponent.
Explore the implementation
The repository map places Mercury in the native C tier of JWCEssentials and identifies its managed companion as Mercury.net. The native API exposes arithmetic and advanced operations through C functions; the C# UltraNumber class adds familiar operators, parsing, conversion, and precision management.
- Native C library and native test driver — headers, implementation, CMake target, and
test.cpp. - Mercury.net projects —
UltraNumber, its xUnit test suite, and example programs. - Repository map — a current guide to project locations, roles, and workspace relationships.
- Canonical Mercury documentation — the full API, representation, precision, stack model, and examples.
Learn by experimenting
The documented UltraNumber example estimates Euler’s number by summing terms of its series. At 64 words, the working mantissa is 2048 bits. The result is printed in Mercury’s hexadecimal representation.
using Mercury.net;
UltraNumber.SetPrecisionAndAllocateStack(64, 1024 * 1024);
UltraNumber e = 0;
UltraNumber factorial = 1;
for (int n = 0; n < 200; n++)
{
if (n > 0) factorial *= (double)n;
e += 1.0 / factorial;
}
Console.WriteLine(e);
This small program is a useful first experiment: change the precision or number of terms, then compare the hexadecimal output. The example comes from the current Mercury reference; it requires the managed wrapper and the native Mercury library to be built and available to the process.
Why hexadecimal? Every eight hexadecimal digits correspond to one 32-bit word. When you increase Mercury’s precision, you can observe additional numerical detail without hiding the representation behind decimal formatting.
When NewAge is needed: NewAge is needed to build this repository’s projects in their documented arrangement. The native CMake target includes common build macros through the NewAge workspace, and the managed projects use NewAge paths for references and post-build staging. Follow the NewAge environment guide for that setup. Once built, using the library requires the native Mercury library to be discoverable by the process; it does not inherently require the NewAge workspace at runtime.
Follow the number all the way down
Read an algorithm, trace a limb, run an example, and inspect the source. Mercury is a working arithmetic library and a place to explore how mathematical ideas become loops, carries, comparisons, and carefully managed temporary memory.
Explore Mercury’s native code or begin with the Mercury article series.