Multiple-precision arithmetic library providing fast GMP, MPFR, and MPC interfaces for Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
gmpy2 provides a sophisticated context system for controlling precision, rounding modes, and exception handling in floating-point and complex number operations. Contexts enable thread-safe computation with fine-grained control over numerical behavior.
The context class manages computational settings and provides context-aware mathematical operations.
class context:
def __init__(self, precision=53, real_prec=None, imag_prec=None,
round=RoundToNearest, real_round=None, imag_round=None,
emax=None, emin=None, subnormalize=False,
trap_underflow=False, trap_overflow=False,
trap_inexact=False, trap_invalid=False,
trap_erange=False, trap_divzero=False,
allow_complex=False, rational_division=False,
allow_release_gil=False):
"""
Create computation context with specified settings.
Args:
precision: Default precision in bits for mpfr operations
real_prec: Precision for real parts (None = use precision)
imag_prec: Precision for imaginary parts (None = use precision)
round: Default rounding mode
real_round: Rounding mode for real parts (None = use round)
imag_round: Rounding mode for imaginary parts (None = use round)
emax: Maximum exponent (None = use MPFR default)
emin: Minimum exponent (None = use MPFR default)
subnormalize: Enable subnormal number handling
trap_underflow: Raise exception on underflow
trap_overflow: Raise exception on overflow
trap_inexact: Raise exception on inexact result
trap_invalid: Raise exception on invalid operation
trap_erange: Raise exception on range error
trap_divzero: Raise exception on division by zero
allow_complex: Allow automatic complex results
rational_division: Use exact rational division
allow_release_gil: Allow GIL release for long operations
"""
# Context manager protocol
def __enter__(self):
"""Enter context manager (sets as current context)."""
def __exit__(self, exc_type, exc_val, exc_tb):
"""Exit context manager (restores previous context)."""
# Context manipulation
def copy(self):
"""Create a copy of this context."""
def clear_flags(self):
"""Clear all exception flags."""
# Properties (all readable and writable)
@property
def precision(self) -> int:
"""Default precision in bits."""
@property
def real_prec(self) -> int:
"""Precision for real parts."""
@property
def imag_prec(self) -> int:
"""Precision for imaginary parts."""
@property
def round(self) -> int:
"""Default rounding mode."""
@property
def emax(self) -> int:
"""Maximum exponent."""
@property
def emin(self) -> int:
"""Minimum exponent."""
# Exception flags (readable)
@property
def underflow(self) -> bool:
"""Underflow flag."""
@property
def overflow(self) -> bool:
"""Overflow flag."""
@property
def inexact(self) -> bool:
"""Inexact result flag."""
@property
def invalid(self) -> bool:
"""Invalid operation flag."""
@property
def erange(self) -> bool:
"""Range error flag."""
@property
def divzero(self) -> bool:
"""Division by zero flag."""Functions for getting, setting, and creating contexts.
def get_context():
"""
Get the current context.
Returns:
context: Current computation context
"""
def set_context(ctx):
"""
Set the current context.
Args:
ctx: Context object to set as current
"""
def local_context(**kwargs):
"""
Create a local context manager with modified settings.
Args:
**kwargs: Context settings to override
Returns:
context: Context manager that temporarily modifies settings
Example:
with local_context(precision=100, round=RoundUp):
# Operations use 100-bit precision and round up
result = gmpy2.sqrt(2)
"""
def ieee(precision):
"""
Create IEEE-compatible context.
Args:
precision: Precision in bits (typically 24, 53, 64, or 113)
Returns:
context: Context with IEEE-compatible settings
Note:
Creates context suitable for IEEE 754 compatibility
"""All mathematical operations in gmpy2 use the current context settings. These include all functions from the mathematical functions module but operate with context precision and rounding.
# Arithmetic operations (context-aware versions)
def add(x, y):
"""Add using current context precision and rounding."""
def sub(x, y):
"""Subtract using current context precision and rounding."""
def mul(x, y):
"""Multiply using current context precision and rounding."""
def div(x, y):
"""Divide using current context precision and rounding."""
def square(x):
"""Square using current context precision and rounding."""
# Mathematical functions (context-aware)
def sqrt(x):
"""Square root using current context."""
def sin(x):
"""Sine using current context."""
def cos(x):
"""Cosine using current context."""
def exp(x):
"""Exponential using current context."""
def log(x):
"""Natural logarithm using current context."""
# ... (all mathematical functions use context)Constants for specifying rounding behavior.
# Rounding mode constants
RoundToNearest: int # Round to nearest (ties to even)
RoundToZero: int # Round toward zero (truncate)
RoundUp: int # Round toward positive infinity
RoundDown: int # Round toward negative infinity
RoundAwayZero: int # Round away from zero
Default: int # Use default/inherited settingAdditional functions for working with contexts and precision.
def get_max_precision():
"""
Get maximum allowed precision.
Returns:
int: Maximum precision in bits supported by MPFR
"""
def get_emax_max():
"""
Get maximum allowed exponent.
Returns:
int: Maximum exponent value
"""
def get_emin_min():
"""
Get minimum allowed exponent.
Returns:
int: Minimum exponent value
"""
def can_round(x, err, rnd1, rnd2, prec):
"""
Test if rounding is deterministic.
Args:
x: Value to test
err: Error bound
rnd1: First rounding mode
rnd2: Second rounding mode
prec: Target precision
Returns:
bool: True if both rounding modes give same result
"""
def check_range(x):
"""
Check if value is in valid range for current context.
Args:
x: Value to check
Returns:
Value, possibly adjusted for range
"""
def free_cache():
"""
Free internal MPFR caches.
Note:
Call this to release memory used by internal caches
"""Functions for creating special floating-point values.
def inf(sign=1):
"""
Create infinity value.
Args:
sign: Sign of infinity (1 for +inf, -1 for -inf)
Returns:
mpfr: Infinity with specified sign
"""
def nan():
"""
Create Not-a-Number value.
Returns:
mpfr: NaN value
"""
def zero(sign=0):
"""
Create signed zero.
Args:
sign: Sign (0 for +0, 1 for -0)
Returns:
mpfr: Signed zero
"""import gmpy2
# Get current context settings
ctx = gmpy2.get_context()
print(f"Current precision: {ctx.precision} bits")
print(f"Current rounding: {ctx.round}")
# Perform calculation with default precision
x = gmpy2.mpfr("1.23456789012345678901234567890")
y = gmpy2.sqrt(2)
print(f"sqrt(2) with default precision: {y}")
# Change precision temporarily
with gmpy2.local_context(precision=100):
z = gmpy2.sqrt(2)
print(f"sqrt(2) with 100-bit precision: {z}")
# Back to default precision
w = gmpy2.sqrt(2)
print(f"sqrt(2) back to default: {w}")import gmpy2
# Compare results at different precisions
precisions = [24, 53, 100, 200]
value = "1.23456789012345678901234567890123456789"
print("Computing sqrt(x) at different precisions:")
for prec in precisions:
with gmpy2.local_context(precision=prec):
x = gmpy2.mpfr(value)
result = gmpy2.sqrt(x)
print(f" {prec:3d} bits: {result}")import gmpy2
# Demonstrate different rounding modes
x = gmpy2.mpfr("1.5")
y = gmpy2.mpfr("2.5")
rounding_modes = [
(gmpy2.RoundToNearest, "To Nearest"),
(gmpy2.RoundToZero, "To Zero"),
(gmpy2.RoundUp, "Up"),
(gmpy2.RoundDown, "Down"),
(gmpy2.RoundAwayZero, "Away from Zero")
]
for mode, name in rounding_modes:
with gmpy2.local_context(round=mode):
result1 = gmpy2.rint(x)
result2 = gmpy2.rint(y)
print(f"{name:15s}: rint({x}) = {result1}, rint({y}) = {result2}")import gmpy2
# Context with exception trapping
trap_context = gmpy2.context(
precision=53,
trap_overflow=True,
trap_underflow=True,
trap_invalid=True,
trap_divzero=True
)
# Normal operation (no exceptions)
print("Normal operations:")
x = gmpy2.mpfr("1e100")
y = gmpy2.mpfr("1e-100")
print(f"Large number: {x}")
print(f"Small number: {y}")
# Operations that might trigger exceptions
try:
with trap_context:
# This might cause overflow
huge = gmpy2.exp(gmpy2.mpfr("1000"))
print(f"exp(1000) = {huge}")
except gmpy2.OverflowResultError:
print("Overflow detected!")
try:
with trap_context:
# Division by zero
result = gmpy2.div(gmpy2.mpfr("1"), gmpy2.mpfr("0"))
print(f"1/0 = {result}")
except gmpy2.DivisionByZeroError:
print("Division by zero detected!")import gmpy2
# Get current context and create modified copy
original_ctx = gmpy2.get_context()
print(f"Original precision: {original_ctx.precision}")
# Create a copy with higher precision
high_prec_ctx = original_ctx.copy()
high_prec_ctx.precision = 200
high_prec_ctx.round = gmpy2.RoundUp
print(f"Modified precision: {high_prec_ctx.precision}")
print(f"Modified rounding: {high_prec_ctx.round}")
# Use the modified context
with high_prec_ctx:
result = gmpy2.sqrt(2)
print(f"High precision sqrt(2): {result}")
# Original context unchanged
print(f"Back to original precision: {original_ctx.precision}")import gmpy2
# Create IEEE-compatible contexts
ieee_single = gmpy2.ieee(24) # IEEE 754 single precision
ieee_double = gmpy2.ieee(53) # IEEE 754 double precision
ieee_extended = gmpy2.ieee(64) # IEEE 754 extended precision
ieee_quad = gmpy2.ieee(113) # IEEE 754 quadruple precision
contexts = [
(ieee_single, "Single (24-bit)"),
(ieee_double, "Double (53-bit)"),
(ieee_extended, "Extended (64-bit)"),
(ieee_quad, "Quad (113-bit)")
]
# Compare computation across IEEE formats
test_value = "1.23456789012345678901234567890"
print("IEEE format comparison:")
for ctx, name in contexts:
with ctx:
x = gmpy2.mpfr(test_value)
result = gmpy2.sin(x)
print(f" {name:18s}: {result}")import gmpy2
# Context with different real and imaginary precision
complex_ctx = gmpy2.context(
real_prec=100, # 100 bits for real part
imag_prec=80, # 80 bits for imaginary part
allow_complex=True # Allow automatic complex results
)
with complex_ctx:
# Create complex number with asymmetric precision
z = gmpy2.mpc("1.23456789012345678901234567890",
"9.87654321098765432109876543210")
print(f"Complex number: {z}")
print(f"Real precision: {z.real.precision}")
print(f"Imaginary precision: {z.imag.precision}")
# Complex operations
exp_z = gmpy2.exp(z)
sqrt_z = gmpy2.sqrt(z)
print(f"exp(z): {exp_z}")
print(f"sqrt(z): {sqrt_z}")import gmpy2
# Create context and monitor flags
ctx = gmpy2.context(precision=50)
with ctx:
# Clear any existing flags
ctx.clear_flags()
# Perform operations that might set flags
x = gmpy2.mpfr("1.0")
y = gmpy2.mpfr("3.0")
result = x / y # Likely inexact
# Check flags
print(f"Result: {result}")
print(f"Inexact flag: {ctx.inexact}")
print(f"Underflow flag: {ctx.underflow}")
print(f"Overflow flag: {ctx.overflow}")
print(f"Invalid flag: {ctx.invalid}")
print(f"Range error flag: {ctx.erange}")
print(f"Division by zero flag: {ctx.divzero}")Install with Tessl CLI
npx tessl i tessl/pypi-gmpy2