---
# System prepended metadata

title: Modular Exponentiation Notes

---

# Modular Exponentiation Notes

## What Is Modular Exponentiation?

Modular exponentiation is exponentiation performed over a modulus.
Simply, it is about calculating a power of a number, then taking the result modulo (remainder after division by) another number.
It’s written like this:
$$ b^e \pmod m $$

In that expression, we'd refer to $b$ as the base, to $e$ as the exponent, and to $m$ as the modulus.

---

### How not to implement modular exponentiation

A really bad approach to implementing modular exponentiation would be something like this: `a ** b % m`, which uses the definition quite literally.

The larger the exponent `b` is, the worse computing `a ** b` becomes.
It is very slow, uses a lot of memory, may cause overflows, and simply - is not efficient.

So instead, we use the **fast modular exponentiation** algorithm, also called **exponentiation by squaring**, which computes the same result efficiently.

---

## Example
Let's calculate `3^13 mod 7` using the Fast Exponentiation Algorithm.

First, write 13 in binary:
```
13 = 1101 (binary)
```

So:
```
3^13 = 3^(8 + 4 + 0 + 1)
     = 3^8 * 3^4 * 3^1
```

Compute powers of 3 mod 7 by squaring each time:

```
3^1 = 3           → 3 mod 7 = 3
3^2 = 9           → 9 mod 7 = 2
3^4 = (3^2)^2 = 2^2 = 4 mod 7
3^8 = (3^4)^2 = 4^2 = 16 mod 7 = 2
```

Now multiply the powers mod 7:

```
3^13 mod 7 = 3^8 * 3^4 * 3^1 mod 7
           = 2 * 4 * 3 = 24
           = 24 mod 7 = 3
```

`3^13 mod 7 = 3`

---

## Python Implementation of Fast Modular Exponentiation
```python
def fast_mod_exp(base, exponent, modulus):
    result = 1
    base %= modulus  # Handle case where base > modulus

    while exponent > 0:
        if exponent % 2 == 1:
            # If the current bit is 1, multiply result by base
            result = (result * base) % modulus
        # Square the base
        base = (base * base) % modulus
        # Move to next bit
        exponent = exponent // 2

    return result
```

## Python's `pow()` and Sagemath's `power_mod`
Both [`pow(a, b, m)`](https://docs.python.org/3/library/functions.html#pow) in Python and [`power_mod(a, b, m)`](https://doc.sagemath.org/html/en/reference/rings_standard/sage/arith/misc.html#sage.arith.misc.power_mod) in SageMath are optimized for modular exponentiation and are fast and reliable.

You can use them to verify our previous exapmle calculation is correct in code:
```python
>>> pow(3, 13, 7)
3
```
```python
sage: power_mod(3, 13, 7)
3
```

---

Both `pow` and `power_mod` support negative exponents for calculating [modular multiplicative inverses](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse):

```python
>>> pow(2, -1, 7)
4
>>> (2 * 4) % 7
1
```
```python
sage: power_mod(2, -1, 7)
4
sage: (2 * 4) % 7
1
```
They are computed efficiently using the [Extended Euclidean Algorithm](https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm).

---

Sage's `power_mod` function is even more powerful, as it can even handle symbols:
```python
sage: R.<x> = ZZ[]
sage: power_mod(3*x, 10, 7)                                          
4*x^10
sage: power_mod(-3*x^2 + 4, 7, 2*x^3 - 5)
x^14 + x^8 + x^6 + x^3 + 962509*x^2 - 791910*x - 698281
```
Generally, it would also work as long as the base and the modulus are elements of a ring that implements the modulo operator %.
