Scalable Integer Type#

JAX, and by extension Jasp, while highly performant for numerical computing, is limited to 64-bit integers. This becomes problematic for applications that require integer representations beyond that range—such as cryptography, arbitrary precision arithmetic, or certain simulations.

The BigInteger class solves this by implementing a scalable integer type that supports arbitrary bit-widths using arrays of smaller integers (32-bit integers). This allows for precise and efficient computation with large integers.

Example#

Here’s a basic example that demonstrates the use of BigInteger:

from qrisp import BigInteger

# Create a BigInteger
# The size is the amount of 32-bit integers, size=4 yields a 128-bit integer
x = BigInteger.create(128, size=4)

print(x())
# Output: 128.0

Note that we use the __call__ method (x()) to approximate the BigInteger as a nicely-readable float.

The BigInteger natively works with the QuantumModulus:

from qrisp import *

@boolean_simulation
def main():
    N = BigInteger.create_static(340282366762482138434845932244680310783, size=4)
    a = BigInteger.create_static(131313, size=4)

    qm = QuantumModulus(N)
    qm[:] = 1

    for i in jrange(10):
        qm *= a

    return measure(qm)()

print(main())
# Output: 1.63367308e+38

Here, we use the create_static method to transform a Python integer that is larger than 64 bits into a BigInteger.

Class Documentation#

class BigInteger(digits: Array)[source]#

Fixed-width, little-endian base-2^32 big integer for JAX.

This type represents non-negative integers using a fixed number of 32-bit limbs (dtype=uint32) in little-endian order (digits[0] is the least significant limb). It is compatible with JAX transformations (jit, vmap, pytrees).

All arithmetic (addition, subtraction, multiplication, shifts, division, modulo, bitwise) is performed modulo 2^(32*n), where n = len(digits). Overflow and underflow beyond the most-significant limb are discarded.

Attributes:
digitsjnp.ndarray

Little-endian limbs (dtype=uint32) of length n.

Notes

  • Width (number of limbs) is determined by digits.shape[0] and remains constant; operations do not change the number of limbs.

  • Operators assume both operands have the same number of limbs.

Static Methods#

BigInteger.create(n, size)

Create a BigInteger using JAX primitives.

BigInteger.create_static(n, size)

Create a BigInteger from Python using pure Python loops.

Operator Overloads#

The BigInteger class supports standard arithmetic and comparison operators through Python’s special methods (dunder methods). This allows you to use BigInteger instances much like native integers.

The following operators are implemented:

  • Arithmetic: + (__add__), - (__sub__), * (__mul__), // (__floordiv__), % (__mod__), ** (__pow__)

  • Bitwise: & (__and__), | (__or__), ^ (__xor__), ~ (__invert__), << (__lshift__), >> (__rshift__)

  • Comparison: == (__eq__), != (__ne__), < (__lt__), <= (__le__), > (__gt__), >= (__ge__)

This enables expressions like:

a = BigInteger.create(42)
b = BigInteger.create(100)

print((a + b)())     # 142.0
print((b - a)())     # 58.0
print((a < b))       # True
print((a << 2)())    # 168.0