.. versionchanged:: 3.11
:meth:`localcontext` now supports setting context attributes through the use of keyword arguments.
+.. function:: IEEEContext(bits)
+
+ Return a context object initialized to the proper values for one of the
+ IEEE interchange formats. The argument must be a multiple of 32 and less
+ than :const:`IEEE_CONTEXT_MAX_BITS`.
+
+ .. versionadded:: next
+
New contexts can also be created using the :class:`Context` constructor
described below. In addition, the module provides three pre-made contexts:
The constants in this section are only relevant for the C module. They
are also included in the pure Python version for compatibility.
-+---------------------+---------------------+-------------------------------+
-| | 32-bit | 64-bit |
-+=====================+=====================+===============================+
-| .. data:: MAX_PREC | ``425000000`` | ``999999999999999999`` |
-+---------------------+---------------------+-------------------------------+
-| .. data:: MAX_EMAX | ``425000000`` | ``999999999999999999`` |
-+---------------------+---------------------+-------------------------------+
-| .. data:: MIN_EMIN | ``-425000000`` | ``-999999999999999999`` |
-+---------------------+---------------------+-------------------------------+
-| .. data:: MIN_ETINY | ``-849999999`` | ``-1999999999999999997`` |
-+---------------------+---------------------+-------------------------------+
-
++---------------------------------+---------------------+-------------------------------+
+| | 32-bit | 64-bit |
++=================================+=====================+===============================+
+| .. data:: MAX_PREC | ``425000000`` | ``999999999999999999`` |
++---------------------------------+---------------------+-------------------------------+
+| .. data:: MAX_EMAX | ``425000000`` | ``999999999999999999`` |
++---------------------------------+---------------------+-------------------------------+
+| .. data:: MIN_EMIN | ``-425000000`` | ``-999999999999999999`` |
++---------------------------------+---------------------+-------------------------------+
+| .. data:: MIN_ETINY | ``-849999999`` | ``-1999999999999999997`` |
++---------------------------------+---------------------+-------------------------------+
+| .. data:: IEEE_CONTEXT_MAX_BITS | ``256`` | ``512`` |
++---------------------------------+---------------------+-------------------------------+
.. data:: HAVE_THREADS
:meth:`Decimal.from_number() <decimal.Decimal.from_number>`.
(Contributed by Serhiy Storchaka in :gh:`121798`.)
+* Expose :func:`decimal.IEEEContext` to support creation of contexts
+ corresponding to the IEEE 754 (2008) decimal interchange formats.
+ (Contributed by Sergey B Kirpichev in :gh:`53032`.)
+
difflib
-------
'ROUND_FLOOR', 'ROUND_UP', 'ROUND_HALF_DOWN', 'ROUND_05UP',
# Functions for manipulating contexts
- 'setcontext', 'getcontext', 'localcontext',
+ 'setcontext', 'getcontext', 'localcontext', 'IEEEContext',
# Limits for the C version for compatibility
- 'MAX_PREC', 'MAX_EMAX', 'MIN_EMIN', 'MIN_ETINY',
+ 'MAX_PREC', 'MAX_EMAX', 'MIN_EMIN', 'MIN_ETINY', 'IEEE_CONTEXT_MAX_BITS',
# C version: compile time choice that enables the thread local context (deprecated, now always true)
'HAVE_THREADS',
MAX_PREC = 999999999999999999
MAX_EMAX = 999999999999999999
MIN_EMIN = -999999999999999999
+ IEEE_CONTEXT_MAX_BITS = 512
else:
MAX_PREC = 425000000
MAX_EMAX = 425000000
MIN_EMIN = -425000000
+ IEEE_CONTEXT_MAX_BITS = 256
MIN_ETINY = MIN_EMIN - (MAX_PREC-1)
return ctx_manager
+def IEEEContext(bits, /):
+ """
+ Return a context object initialized to the proper values for one of the
+ IEEE interchange formats. The argument must be a multiple of 32 and less
+ than IEEE_CONTEXT_MAX_BITS.
+ """
+ if bits <= 0 or bits > IEEE_CONTEXT_MAX_BITS or bits % 32:
+ raise ValueError("argument must be a multiple of 32, "
+ f"with a maximum of {IEEE_CONTEXT_MAX_BITS}")
+
+ ctx = Context()
+ ctx.prec = 9 * (bits//32) - 2
+ ctx.Emax = 3 * (1 << (bits//16 + 3))
+ ctx.Emin = 1 - ctx.Emax
+ ctx.rounding = ROUND_HALF_EVEN
+ ctx.clamp = 1
+ ctx.traps = dict.fromkeys(_signals, False)
+
+ return ctx
+
+
##### Decimal class #######################################################
# Do not subclass Decimal from numbers.Real and do not register it as such
class PyContextSubclassing(ContextSubclassing, unittest.TestCase):
decimal = P
+class IEEEContexts:
+
+ def test_ieee_context(self):
+ # issue 8786: Add support for IEEE 754 contexts to decimal module.
+ IEEEContext = self.decimal.IEEEContext
+
+ def assert_rest(self, context):
+ self.assertEqual(context.clamp, 1)
+ assert_signals(self, context, 'traps', [])
+ assert_signals(self, context, 'flags', [])
+
+ c = IEEEContext(32)
+ self.assertEqual(c.prec, 7)
+ self.assertEqual(c.Emax, 96)
+ self.assertEqual(c.Emin, -95)
+ assert_rest(self, c)
+
+ c = IEEEContext(64)
+ self.assertEqual(c.prec, 16)
+ self.assertEqual(c.Emax, 384)
+ self.assertEqual(c.Emin, -383)
+ assert_rest(self, c)
+
+ c = IEEEContext(128)
+ self.assertEqual(c.prec, 34)
+ self.assertEqual(c.Emax, 6144)
+ self.assertEqual(c.Emin, -6143)
+ assert_rest(self, c)
+
+ # Invalid values
+ self.assertRaises(ValueError, IEEEContext, -1)
+ self.assertRaises(ValueError, IEEEContext, 123)
+ self.assertRaises(ValueError, IEEEContext, 1024)
+
+ def test_constants(self):
+ # IEEEContext
+ IEEE_CONTEXT_MAX_BITS = self.decimal.IEEE_CONTEXT_MAX_BITS
+ self.assertIn(IEEE_CONTEXT_MAX_BITS, {256, 512})
+
+@requires_cdecimal
+class CIEEEContexts(IEEEContexts, unittest.TestCase):
+ decimal = C
+class PyIEEEContexts(IEEEContexts, unittest.TestCase):
+ decimal = P
+
@skip_if_extra_functionality
@requires_cdecimal
class CheckAttributes(unittest.TestCase):
self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
+ self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, P.IEEE_CONTEXT_MAX_BITS)
self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
class CFunctionality(unittest.TestCase):
"""Extra functionality in _decimal"""
- @requires_extra_functionality
- def test_c_ieee_context(self):
- # issue 8786: Add support for IEEE 754 contexts to decimal module.
- IEEEContext = C.IEEEContext
- DECIMAL32 = C.DECIMAL32
- DECIMAL64 = C.DECIMAL64
- DECIMAL128 = C.DECIMAL128
-
- def assert_rest(self, context):
- self.assertEqual(context.clamp, 1)
- assert_signals(self, context, 'traps', [])
- assert_signals(self, context, 'flags', [])
-
- c = IEEEContext(DECIMAL32)
- self.assertEqual(c.prec, 7)
- self.assertEqual(c.Emax, 96)
- self.assertEqual(c.Emin, -95)
- assert_rest(self, c)
-
- c = IEEEContext(DECIMAL64)
- self.assertEqual(c.prec, 16)
- self.assertEqual(c.Emax, 384)
- self.assertEqual(c.Emin, -383)
- assert_rest(self, c)
-
- c = IEEEContext(DECIMAL128)
- self.assertEqual(c.prec, 34)
- self.assertEqual(c.Emax, 6144)
- self.assertEqual(c.Emin, -6143)
- assert_rest(self, c)
-
- # Invalid values
- self.assertRaises(OverflowError, IEEEContext, 2**63)
- self.assertRaises(ValueError, IEEEContext, -1)
- self.assertRaises(ValueError, IEEEContext, 1024)
-
@requires_extra_functionality
def test_c_context(self):
Context = C.Context
C.DecSubnormal, C.DecUnderflow
)
- # IEEEContext
- self.assertEqual(C.DECIMAL32, 32)
- self.assertEqual(C.DECIMAL64, 64)
- self.assertEqual(C.DECIMAL128, 128)
- self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
-
# Conditions
for i, v in enumerate(cond):
self.assertEqual(v, 1<<i)
--- /dev/null
+Expose :func:`decimal.IEEEContext` to support creation of contexts
+corresponding to the IEEE 754 (2008) decimal interchange formats.
+Patch by Sergey B Kirpichev.
CtxCaps(v) = 1;
}
-#ifdef EXTRA_FUNCTIONALITY
/* Factory function for creating IEEE interchange format contexts */
static PyObject *
ieee_context(PyObject *module, PyObject *v)
return NULL;
}
-#endif
static PyObject *
context_copy(PyObject *self, PyObject *Py_UNUSED(dummy))
{ "getcontext", PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext},
{ "setcontext", PyDec_SetCurrentContext, METH_O, doc_setcontext},
{ "localcontext", _PyCFunction_CAST(ctxmanager_new), METH_VARARGS|METH_KEYWORDS, doc_localcontext},
-#ifdef EXTRA_FUNCTIONALITY
{ "IEEEContext", ieee_context, METH_O, doc_ieee_context},
-#endif
{ NULL, NULL, 1, NULL }
};
struct int_constmap { const char *name; int val; };
static struct int_constmap int_constants [] = {
/* int constants */
+ {"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
#ifdef EXTRA_FUNCTIONALITY
{"DECIMAL32", MPD_DECIMAL32},
{"DECIMAL64", MPD_DECIMAL64},
{"DECIMAL128", MPD_DECIMAL128},
- {"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
/* int condition flags */
{"DecClamped", MPD_Clamped},
{"DecConversionSyntax", MPD_Conversion_syntax},
default context is used.\n\
\n");
-#ifdef EXTRA_FUNCTIONALITY
PyDoc_STRVAR(doc_ieee_context,
"IEEEContext($module, bits, /)\n--\n\n\
Return a context object initialized to the proper values for one of the\n\
IEEE interchange formats. The argument must be a multiple of 32 and less\n\
-than IEEE_CONTEXT_MAX_BITS. For the most common values, the constants\n\
-DECIMAL32, DECIMAL64 and DECIMAL128 are provided.\n\
+than IEEE_CONTEXT_MAX_BITS.\n\
\n");
-#endif
/******************************************************************************/