Skip to content

Commit

Permalink
Merge pull request #460 from skirpichev/454-local_context-vs-context
Browse files Browse the repository at this point in the history
Deprecate local_context() and update contexts.rst
  • Loading branch information
casevh authored Dec 5, 2023
2 parents 7bddc70 + 7a40966 commit 831782a
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 429 deletions.
110 changes: 7 additions & 103 deletions docs/contexts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ Contexts

.. currentmodule:: gmpy2

`context()` creates a new context with all options set to default.
`set_context()` will set the active context. `get_context()` will
return a reference to the active context. Note that contexts are mutable:
modifying the reference returned by `get_context()` will modify the active
context until a new context is enabled with `set_context()`. The
`~context.copy()` method of a context will return a copy of the context.
`context()` creates a new context. `set_context()` will set the active
context. `get_context()` will return a reference to the active context. Note
that contexts are mutable: modifying the reference returned by `get_context()`
will modify the active context until a new context is enabled with
`set_context()`. The `context.copy()` method will return a copy of the
context. Contexts that implement the standard *single*, *double*, and
*quadruple* precision floating point types can be created using `ieee()`.

Context Type
------------
Expand All @@ -24,100 +25,3 @@ Context Functions
.. autofunction:: ieee
.. autofunction:: local_context
.. autofunction:: set_context

Contexts and the with statement
-------------------------------

Contexts can also be used in conjunction with Python's :keyword:`with`
statement to temporarily change the context settings for a block of code and
then restore the original settings when the block of code exits.

`local_context` saves the current context and then creates a new context
based on the context passed as the first argument, or the current context
if no context is passed. The new context is modified if any optional keyword
arguments are given. The original active context is restored when the block
completes.

In the following example, the current context is saved by `local_context`
and then the block begins with a copy of the default context and the precision
set to 100. When the block is finished, the original context is restored.

.. doctest::

>>> import gmpy2
>>> print(gmpy2.sqrt(2))
1.4142135623730951
>>> with gmpy2.local_context(gmpy2.context(), precision=100):
... print(gmpy2.sqrt(2))
... gmpy2.get_context().precision += 100
... print(gmpy2.sqrt(2))
...
1.4142135623730950488016887242092
1.4142135623730950488016887242096980785696718753769480731766796
>>> print(gmpy2.sqrt(2))
1.4142135623730951

Beginning in gmpy2 2.2.0, the :keyword:`with` statement can directly without
the use of `local_context`.

.. doctest::

>>> import gmpy2
>>> print(gmpy2.sqrt(2))
1.4142135623730951
>>> with gmpy2.context(precision=100):
... print(gmpy2.sqrt(2))
... gmpy2.get_context().precision += 100
... print(gmpy2.sqrt(2))
...
1.4142135623730950488016887242092
1.4142135623730950488016887242096980785696718753769480731766796
>>> print(gmpy2.sqrt(2))
1.4142135623730951

Nested contexts and coding style
--------------------------------

The ``with ... as ctx:`` coding style is commonly used. It does not behave
as expected with nested contexts. The first example shows the unexpected
behavior. The precision of sqrt(2) is correct since the global context
is properly undated. But ctx is not updated when the block exits. You
should always use get_context() to refer to the currently active context.

.. doctest::

>>> import gmpy2
>>> from gmpy2 import ieee, sqrt, get_context
>>> with ieee(64) as ctx:
... print(ctx.precision, sqrt(2))
... with ieee(128) as ctx:
... print(ctx.precision, sqrt(2))
... print(ctx.precision, sqrt(2))
...
53 1.4142135623730951
113 1.41421356237309504880168872420969798
113 1.4142135623730951

This example uses the recommended coding style.

.. doctest::

>>> import gmpy2
>>> from gmpy2 import ieee, sqrt, get_context
>>> with ieee(64):
... print(get_context().precision, sqrt(2))
... with ieee(128):
... print(get_context().precision, sqrt(2))
... print(get_context().precision, sqrt(2))
...
53 1.4142135623730951
113 1.41421356237309504880168872420969798
53 1.4142135623730951

Comments on the ieee context
----------------------------

Contexts that implement the standard *single*, *double*, and *quadruple*
precision floating point types can be created using ieee(32), ieee(64),
and ieee(128). Higher precisions such as ieee(1024) are also supported.

13 changes: 8 additions & 5 deletions docs/tutorial.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,21 @@ will be returned.
>>> sqrt(mpfr(-2))
mpc('0.0+1.4142135623730951j')

Contexts can also be used in conjunction with Python's :keyword:`with`
statement to temporarily change the context settings for a block of code.
Contexts can also be used as context managers in conjunction with Python's
:keyword:`with` statement to temporarily change the current context settings
for a block of code.

.. doctest::

>>> with local_context() as ctx:
>>> print(const_pi())
3.1415926535897931
>>> with context(precision=100) as ctx:
... print(const_pi())
... ctx.precision += 20
... print(const_pi())
...
3.1415926535897931
3.1415926535897932384628
3.1415926535897932384626433832793
3.1415926535897932384626433832795028847
>>> print(const_pi())
3.1415926535897931

Expand Down
1 change: 0 additions & 1 deletion gmpy2/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .gmpy2 import *
from .gmpy2 import __version__
from .gmpy2 import _local_context
# Internal variables/functions are not imported by * above.
# These are used by some python level functions and are needed
# at the top level.
Expand Down
7 changes: 0 additions & 7 deletions src/gmpy2.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,6 @@ static PyMethodDef Pygmpy_methods [] =
{ "lgamma", GMPy_Context_Lgamma, METH_O, GMPy_doc_function_lgamma },
{ "li2", GMPy_Context_Li2, METH_O, GMPy_doc_function_li2 },
{ "lngamma", GMPy_Context_Lngamma, METH_O, GMPy_doc_function_lngamma },
{ "_local_context", (PyCFunction)GMPy_CTXT_Local_Context2, METH_VARARGS | METH_KEYWORDS, GMPy_doc_local_context2 },
{ "local_context", (PyCFunction)GMPy_CTXT_Local, METH_VARARGS | METH_KEYWORDS, GMPy_doc_local_context },
{ "log", GMPy_Context_Log, METH_O, GMPy_doc_function_log },
{ "log1p", GMPy_Context_Log1p, METH_O, GMPy_doc_function_log1p },
Expand Down Expand Up @@ -1059,11 +1058,6 @@ PyMODINIT_FUNC PyInit_gmpy2(void)
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&CTXT_Manager_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
/* LCOV_EXCL_STOP */
}
if (PyType_Ready(&MPC_Type) < 0) {
/* LCOV_EXCL_START */
return NULL;;
Expand Down Expand Up @@ -1282,7 +1276,6 @@ PyMODINIT_FUNC PyInit_gmpy2(void)
GMPy_C_API[MPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[XMPC_Type_NUM] = (void*)&MPC_Type;
GMPy_C_API[CTXT_Type_NUM] = (void*)&CTXT_Type;
GMPy_C_API[CTXT_Manager_Type_NUM] = (void*)&CTXT_Manager_Type;
GMPy_C_API[RandomState_Type_NUM] = (void*)&RandomState_Type;

GMPy_C_API[GMPy_MPZ_New_NUM] = (void*)GMPy_MPZ_New;
Expand Down
10 changes: 0 additions & 10 deletions src/gmpy2.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ extern "C" {
* MPC_Object
* XMPC_Object (mutable version of MPC_Object)
* CTXT_Object
* CTXT_Manager_Object
* RandomState_Object
*/

Expand Down Expand Up @@ -189,14 +188,6 @@ typedef struct {
PyObject *token;
} CTXT_Object;

typedef struct {
PyObject_HEAD
CTXT_Object *new_context; /* Context that will be returned when
* __enter__ is called. */
CTXT_Object *old_context; /* Context that will restored when
* __exit__ is called. */
} CTXT_Manager_Object;

#define MPZ(obj) (((MPZ_Object*)(obj))->z)
#define MPQ(obj) (((MPQ_Object*)(obj))->q)
#define MPFR(obj) (((MPFR_Object*)(obj))->f)
Expand All @@ -213,7 +204,6 @@ typedef struct {
#define MPC_Type_NUM 6
#define XMPC_Type_NUM 7
#define CTXT_Type_NUM 8
#define CTXT_Manager_Type_NUM 9
#define RandomState_Type_NUM 10

/* The following functions are found in gmpy2_cache. */
Expand Down
Loading

0 comments on commit 831782a

Please sign in to comment.