0
# Context Management
1
2
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.
3
4
## Capabilities
5
6
### Context Class
7
8
The context class manages computational settings and provides context-aware mathematical operations.
9
10
```python { .api }
11
class context:
12
def __init__(self, precision=53, real_prec=None, imag_prec=None,
13
round=RoundToNearest, real_round=None, imag_round=None,
14
emax=None, emin=None, subnormalize=False,
15
trap_underflow=False, trap_overflow=False,
16
trap_inexact=False, trap_invalid=False,
17
trap_erange=False, trap_divzero=False,
18
allow_complex=False, rational_division=False,
19
allow_release_gil=False):
20
"""
21
Create computation context with specified settings.
22
23
Args:
24
precision: Default precision in bits for mpfr operations
25
real_prec: Precision for real parts (None = use precision)
26
imag_prec: Precision for imaginary parts (None = use precision)
27
round: Default rounding mode
28
real_round: Rounding mode for real parts (None = use round)
29
imag_round: Rounding mode for imaginary parts (None = use round)
30
emax: Maximum exponent (None = use MPFR default)
31
emin: Minimum exponent (None = use MPFR default)
32
subnormalize: Enable subnormal number handling
33
trap_underflow: Raise exception on underflow
34
trap_overflow: Raise exception on overflow
35
trap_inexact: Raise exception on inexact result
36
trap_invalid: Raise exception on invalid operation
37
trap_erange: Raise exception on range error
38
trap_divzero: Raise exception on division by zero
39
allow_complex: Allow automatic complex results
40
rational_division: Use exact rational division
41
allow_release_gil: Allow GIL release for long operations
42
"""
43
44
# Context manager protocol
45
def __enter__(self):
46
"""Enter context manager (sets as current context)."""
47
48
def __exit__(self, exc_type, exc_val, exc_tb):
49
"""Exit context manager (restores previous context)."""
50
51
# Context manipulation
52
def copy(self):
53
"""Create a copy of this context."""
54
55
def clear_flags(self):
56
"""Clear all exception flags."""
57
58
# Properties (all readable and writable)
59
@property
60
def precision(self) -> int:
61
"""Default precision in bits."""
62
63
@property
64
def real_prec(self) -> int:
65
"""Precision for real parts."""
66
67
@property
68
def imag_prec(self) -> int:
69
"""Precision for imaginary parts."""
70
71
@property
72
def round(self) -> int:
73
"""Default rounding mode."""
74
75
@property
76
def emax(self) -> int:
77
"""Maximum exponent."""
78
79
@property
80
def emin(self) -> int:
81
"""Minimum exponent."""
82
83
# Exception flags (readable)
84
@property
85
def underflow(self) -> bool:
86
"""Underflow flag."""
87
88
@property
89
def overflow(self) -> bool:
90
"""Overflow flag."""
91
92
@property
93
def inexact(self) -> bool:
94
"""Inexact result flag."""
95
96
@property
97
def invalid(self) -> bool:
98
"""Invalid operation flag."""
99
100
@property
101
def erange(self) -> bool:
102
"""Range error flag."""
103
104
@property
105
def divzero(self) -> bool:
106
"""Division by zero flag."""
107
```
108
109
### Context Management Functions
110
111
Functions for getting, setting, and creating contexts.
112
113
```python { .api }
114
def get_context():
115
"""
116
Get the current context.
117
118
Returns:
119
context: Current computation context
120
"""
121
122
def set_context(ctx):
123
"""
124
Set the current context.
125
126
Args:
127
ctx: Context object to set as current
128
"""
129
130
def local_context(**kwargs):
131
"""
132
Create a local context manager with modified settings.
133
134
Args:
135
**kwargs: Context settings to override
136
137
Returns:
138
context: Context manager that temporarily modifies settings
139
140
Example:
141
with local_context(precision=100, round=RoundUp):
142
# Operations use 100-bit precision and round up
143
result = gmpy2.sqrt(2)
144
"""
145
146
def ieee(precision):
147
"""
148
Create IEEE-compatible context.
149
150
Args:
151
precision: Precision in bits (typically 24, 53, 64, or 113)
152
153
Returns:
154
context: Context with IEEE-compatible settings
155
156
Note:
157
Creates context suitable for IEEE 754 compatibility
158
"""
159
```
160
161
### Context-Aware Mathematical Operations
162
163
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.
164
165
```python { .api }
166
# Arithmetic operations (context-aware versions)
167
def add(x, y):
168
"""Add using current context precision and rounding."""
169
170
def sub(x, y):
171
"""Subtract using current context precision and rounding."""
172
173
def mul(x, y):
174
"""Multiply using current context precision and rounding."""
175
176
def div(x, y):
177
"""Divide using current context precision and rounding."""
178
179
def square(x):
180
"""Square using current context precision and rounding."""
181
182
# Mathematical functions (context-aware)
183
def sqrt(x):
184
"""Square root using current context."""
185
186
def sin(x):
187
"""Sine using current context."""
188
189
def cos(x):
190
"""Cosine using current context."""
191
192
def exp(x):
193
"""Exponential using current context."""
194
195
def log(x):
196
"""Natural logarithm using current context."""
197
198
# ... (all mathematical functions use context)
199
```
200
201
### Rounding Mode Constants
202
203
Constants for specifying rounding behavior.
204
205
```python { .api }
206
# Rounding mode constants
207
RoundToNearest: int # Round to nearest (ties to even)
208
RoundToZero: int # Round toward zero (truncate)
209
RoundUp: int # Round toward positive infinity
210
RoundDown: int # Round toward negative infinity
211
RoundAwayZero: int # Round away from zero
212
Default: int # Use default/inherited setting
213
```
214
215
### Context Utilities
216
217
Additional functions for working with contexts and precision.
218
219
```python { .api }
220
def get_max_precision():
221
"""
222
Get maximum allowed precision.
223
224
Returns:
225
int: Maximum precision in bits supported by MPFR
226
"""
227
228
def get_emax_max():
229
"""
230
Get maximum allowed exponent.
231
232
Returns:
233
int: Maximum exponent value
234
"""
235
236
def get_emin_min():
237
"""
238
Get minimum allowed exponent.
239
240
Returns:
241
int: Minimum exponent value
242
"""
243
244
def can_round(x, err, rnd1, rnd2, prec):
245
"""
246
Test if rounding is deterministic.
247
248
Args:
249
x: Value to test
250
err: Error bound
251
rnd1: First rounding mode
252
rnd2: Second rounding mode
253
prec: Target precision
254
255
Returns:
256
bool: True if both rounding modes give same result
257
"""
258
259
def check_range(x):
260
"""
261
Check if value is in valid range for current context.
262
263
Args:
264
x: Value to check
265
266
Returns:
267
Value, possibly adjusted for range
268
"""
269
270
def free_cache():
271
"""
272
Free internal MPFR caches.
273
274
Note:
275
Call this to release memory used by internal caches
276
"""
277
```
278
279
### Special Values
280
281
Functions for creating special floating-point values.
282
283
```python { .api }
284
def inf(sign=1):
285
"""
286
Create infinity value.
287
288
Args:
289
sign: Sign of infinity (1 for +inf, -1 for -inf)
290
291
Returns:
292
mpfr: Infinity with specified sign
293
"""
294
295
def nan():
296
"""
297
Create Not-a-Number value.
298
299
Returns:
300
mpfr: NaN value
301
"""
302
303
def zero(sign=0):
304
"""
305
Create signed zero.
306
307
Args:
308
sign: Sign (0 for +0, 1 for -0)
309
310
Returns:
311
mpfr: Signed zero
312
"""
313
```
314
315
## Usage Examples
316
317
### Basic Context Usage
318
319
```python
320
import gmpy2
321
322
# Get current context settings
323
ctx = gmpy2.get_context()
324
print(f"Current precision: {ctx.precision} bits")
325
print(f"Current rounding: {ctx.round}")
326
327
# Perform calculation with default precision
328
x = gmpy2.mpfr("1.23456789012345678901234567890")
329
y = gmpy2.sqrt(2)
330
print(f"sqrt(2) with default precision: {y}")
331
332
# Change precision temporarily
333
with gmpy2.local_context(precision=100):
334
z = gmpy2.sqrt(2)
335
print(f"sqrt(2) with 100-bit precision: {z}")
336
337
# Back to default precision
338
w = gmpy2.sqrt(2)
339
print(f"sqrt(2) back to default: {w}")
340
```
341
342
### Precision Comparison
343
344
```python
345
import gmpy2
346
347
# Compare results at different precisions
348
precisions = [24, 53, 100, 200]
349
value = "1.23456789012345678901234567890123456789"
350
351
print("Computing sqrt(x) at different precisions:")
352
for prec in precisions:
353
with gmpy2.local_context(precision=prec):
354
x = gmpy2.mpfr(value)
355
result = gmpy2.sqrt(x)
356
print(f" {prec:3d} bits: {result}")
357
```
358
359
### Rounding Mode Effects
360
361
```python
362
import gmpy2
363
364
# Demonstrate different rounding modes
365
x = gmpy2.mpfr("1.5")
366
y = gmpy2.mpfr("2.5")
367
368
rounding_modes = [
369
(gmpy2.RoundToNearest, "To Nearest"),
370
(gmpy2.RoundToZero, "To Zero"),
371
(gmpy2.RoundUp, "Up"),
372
(gmpy2.RoundDown, "Down"),
373
(gmpy2.RoundAwayZero, "Away from Zero")
374
]
375
376
for mode, name in rounding_modes:
377
with gmpy2.local_context(round=mode):
378
result1 = gmpy2.rint(x)
379
result2 = gmpy2.rint(y)
380
print(f"{name:15s}: rint({x}) = {result1}, rint({y}) = {result2}")
381
```
382
383
### Exception Handling
384
385
```python
386
import gmpy2
387
388
# Context with exception trapping
389
trap_context = gmpy2.context(
390
precision=53,
391
trap_overflow=True,
392
trap_underflow=True,
393
trap_invalid=True,
394
trap_divzero=True
395
)
396
397
# Normal operation (no exceptions)
398
print("Normal operations:")
399
x = gmpy2.mpfr("1e100")
400
y = gmpy2.mpfr("1e-100")
401
print(f"Large number: {x}")
402
print(f"Small number: {y}")
403
404
# Operations that might trigger exceptions
405
try:
406
with trap_context:
407
# This might cause overflow
408
huge = gmpy2.exp(gmpy2.mpfr("1000"))
409
print(f"exp(1000) = {huge}")
410
except gmpy2.OverflowResultError:
411
print("Overflow detected!")
412
413
try:
414
with trap_context:
415
# Division by zero
416
result = gmpy2.div(gmpy2.mpfr("1"), gmpy2.mpfr("0"))
417
print(f"1/0 = {result}")
418
except gmpy2.DivisionByZeroError:
419
print("Division by zero detected!")
420
```
421
422
### Context Copying and Modification
423
424
```python
425
import gmpy2
426
427
# Get current context and create modified copy
428
original_ctx = gmpy2.get_context()
429
print(f"Original precision: {original_ctx.precision}")
430
431
# Create a copy with higher precision
432
high_prec_ctx = original_ctx.copy()
433
high_prec_ctx.precision = 200
434
high_prec_ctx.round = gmpy2.RoundUp
435
436
print(f"Modified precision: {high_prec_ctx.precision}")
437
print(f"Modified rounding: {high_prec_ctx.round}")
438
439
# Use the modified context
440
with high_prec_ctx:
441
result = gmpy2.sqrt(2)
442
print(f"High precision sqrt(2): {result}")
443
444
# Original context unchanged
445
print(f"Back to original precision: {original_ctx.precision}")
446
```
447
448
### IEEE Compatibility
449
450
```python
451
import gmpy2
452
453
# Create IEEE-compatible contexts
454
ieee_single = gmpy2.ieee(24) # IEEE 754 single precision
455
ieee_double = gmpy2.ieee(53) # IEEE 754 double precision
456
ieee_extended = gmpy2.ieee(64) # IEEE 754 extended precision
457
ieee_quad = gmpy2.ieee(113) # IEEE 754 quadruple precision
458
459
contexts = [
460
(ieee_single, "Single (24-bit)"),
461
(ieee_double, "Double (53-bit)"),
462
(ieee_extended, "Extended (64-bit)"),
463
(ieee_quad, "Quad (113-bit)")
464
]
465
466
# Compare computation across IEEE formats
467
test_value = "1.23456789012345678901234567890"
468
469
print("IEEE format comparison:")
470
for ctx, name in contexts:
471
with ctx:
472
x = gmpy2.mpfr(test_value)
473
result = gmpy2.sin(x)
474
print(f" {name:18s}: {result}")
475
```
476
477
### Complex Context Settings
478
479
```python
480
import gmpy2
481
482
# Context with different real and imaginary precision
483
complex_ctx = gmpy2.context(
484
real_prec=100, # 100 bits for real part
485
imag_prec=80, # 80 bits for imaginary part
486
allow_complex=True # Allow automatic complex results
487
)
488
489
with complex_ctx:
490
# Create complex number with asymmetric precision
491
z = gmpy2.mpc("1.23456789012345678901234567890",
492
"9.87654321098765432109876543210")
493
494
print(f"Complex number: {z}")
495
print(f"Real precision: {z.real.precision}")
496
print(f"Imaginary precision: {z.imag.precision}")
497
498
# Complex operations
499
exp_z = gmpy2.exp(z)
500
sqrt_z = gmpy2.sqrt(z)
501
502
print(f"exp(z): {exp_z}")
503
print(f"sqrt(z): {sqrt_z}")
504
```
505
506
### Context State Monitoring
507
508
```python
509
import gmpy2
510
511
# Create context and monitor flags
512
ctx = gmpy2.context(precision=50)
513
514
with ctx:
515
# Clear any existing flags
516
ctx.clear_flags()
517
518
# Perform operations that might set flags
519
x = gmpy2.mpfr("1.0")
520
y = gmpy2.mpfr("3.0")
521
result = x / y # Likely inexact
522
523
# Check flags
524
print(f"Result: {result}")
525
print(f"Inexact flag: {ctx.inexact}")
526
print(f"Underflow flag: {ctx.underflow}")
527
print(f"Overflow flag: {ctx.overflow}")
528
print(f"Invalid flag: {ctx.invalid}")
529
print(f"Range error flag: {ctx.erange}")
530
print(f"Division by zero flag: {ctx.divzero}")
531
```