The Power Tier: Binary Squaring and the Symmetry of Fractional Exponents

With the linear and geometric foundations of the Mercury engine established, we now step into the highest foundational level of mathematics: The Power Tier.

Unlike addition or multiplication, exponential growth is completely asymmetrical. The base and the exponent play entirely different physical roles. Because of this asymmetry, the inverse operations required to deconstruct an exponent split into two distinct, specialized functions: roots and logarithms.

$$C = A^B \implies A = \sqrt[B]{C} \quad \text{and} \quad B = \log_A(C)$$

In Sigma Language notation, this structural relationship looks like this:

  • C = A pow B; (Exponential combination)

  • A = C root B; (Solving for the Base)

  • B = C log A; (Solving for the Exponent)

In the lower tiers, the inverse operation could often be visualized as a direct reversal: subtraction reverses addition, and division reverses multiplication. In the Power Tier, the reversal splits because the two inputs have different meanings. Solving for the base requires root; solving for the exponent requires log.

Before we can look at how Mercury solves for missing bases and exponents, we first need to look at the forward operation: mercuryPow.

The Binary Shortcut: Exponentiation by Squaring

If you need to calculate $A^{100}$, the naive mathematical approach is to multiply $A \cdot A \cdot A \dots$ one hundred times. For arbitrary-precision numbers scaling across thousands of base-$2^{32}$ places, executing that many massive multiplications would bring a CPU to its knees.

Instead, Mercury uses an algorithmic shortcut called “exponentiation by squaring.” Because Mercury stores the exponent (B) in a native binary format, the engine can read the bits of B to determine exactly which prepared powers of A need to be multiplied into the result.

For example, raising A to the power of 3 normally looks like:

A * A * A

But 3 in binary is 11, meaning:

3 = 2 + 1

So the same expression can be rewritten as:

A^3 = A^2 * A^1

Mercury prepares those powers by repeatedly squaring the running base:

A^1 → A^2 → A^4 → A^8 → ...

Then, whenever the corresponding exponent bit is 1, that prepared power is multiplied into the result. The exponent’s binary digits become instructions for which powers of A participate in the final product.

This same bit-selection principle also appears one tier below in binary multiplication. To multiply by 3, we can write:

A * 3 = A + A + A = (A * 2) + A

Since 3 is binary 11, the multiplication engine can prepare A, A * 2, A * 4, and so on, then add the prepared values whose multiplier bits are set.

The Power Tier follows the same pattern at a higher order. Instead of preparing values with doubling and combining them with addition, it prepares powers with squaring and combines them with multiplication. The key is to use the correct construction and combination operations for the tier.

Here is the exact loop inside mercuryPow that handles the whole-number portion of the exponent:

// Process the integer bits (from bit 0 up to the highest bit)
for (int bit = 0; bit <= highBit; bit++) {
    
    // If the bit is 1, multiply our running base 'p' into our result 'r'
    if (mercuryGetBit(stack, Precision, bit, b) == 1) {
        mercuryMul(stack, Precision + 1, r, p, r);
    }

    // Always square the running base 'p' to prepare for the next bit
    if (bit != highBit) mercurySqr(stack, Precision + 1, p, p);
}

By reading the binary places and squaring the base at every step (e.g., $A^1 \to A^2 \to A^4 \to A^8$), Mercury geometrically skips over the redundant math. To calculate $A^{100}$, the engine does not need 100 multiplications—it only needs a handful of squares and strategic multiplies, dynamically arriving at the answer in a fraction of the time.

The Mirror: Fractional Exponents and Tier Symmetry

What happens if the exponent is not a whole integer? What if we need to calculate $A^{2.5}$?

This is where the true symmetry of the Power Tier reveals itself in the silicon. The identity position (bit $0$) acts as a mirror. When moving left into positive bits ($1, 2, 3 \dots$), Mercury scales the base by squaring it. But when moving right into the fractional bits ($-1, -2, -3 \dots$), Mercury must scale the base in the exact opposite direction.

To do this, it is mathematically forced to call upon its tier sibling: the square root.

// Process the fractional bits (from bit -1 down to the lowest bit)
for (int bit = -1; bit >= lowBit; bit--) {
    
    // Always square root the running base 'p' to prepare for the next fractional bit
    mercurySqrt(stack, Precision + 1, p, p);

    // If the bit is 1, multiply our running base 'p' into our result 'r'
    if (mercuryGetBit(stack, Precision, bit, b) == 1) {
        mercuryMul(stack, Precision + 1, r, p, r);
    }
}

Bit $-1$ represents $A^{0.5}$, which is exactly $\sqrt{A}$. Bit $-2$ represents $A^{0.25}$, which is the square root of the square root.

By simply swapping mercurySqr for mercurySqrt as it crosses the binary point, the engine seamlessly handles massive fractional powers. It proves that within the Power Tier, these operations are not isolated functions—they are fundamentally dependent on one another. You literally cannot build a comprehensive pow engine without a sqrt engine.

Implementation Note: The Guard Place

If you look closely at the C loops above, you will notice that the math functions are called with Precision + 1 rather than the standard Precision.

When you square massive numbers repeatedly, minor rounding errors at the absolute lowest bits can cascade upwards and corrupt the final answer. By temporarily computing the entire exponentiation sequence with one extra 32-bit “guard place,” Mercury insulates the working precision from cumulative geometric error. Once the calculation is completely finished, the guard place is cleanly truncated, leaving a pristine result.

Up Next: The Convergence

Now that we have seen how mercuryPow utilizes mercurySqrt to navigate fractional exponents, we are perfectly positioned to tackle the most complex function in the library.

In our next post, we will look at mercuryLog, and explore how Mercury dynamically hunts for a missing exponent by using roots and powers to converge on the answer bit by bit.

JWCEssentials on GitHub

JWCEssentials/C/Mercury/Mercury.c

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>


The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.