Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2008-2012 Stefan Krah. All rights reserved.
3 : : *
4 : : * Redistribution and use in source and binary forms, with or without
5 : : * modification, are permitted provided that the following conditions
6 : : * are met:
7 : : *
8 : : * 1. Redistributions of source code must retain the above copyright
9 : : * notice, this list of conditions and the following disclaimer.
10 : : *
11 : : * 2. Redistributions in binary form must reproduce the above copyright
12 : : * notice, this list of conditions and the following disclaimer in the
13 : : * documentation and/or other materials provided with the distribution.
14 : : *
15 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
16 : : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 : : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 : : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 : : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 : : * SUCH DAMAGE.
26 : : */
27 : :
28 : : #ifndef Py_BUILD_CORE_BUILTIN
29 : : # define Py_BUILD_CORE_MODULE 1
30 : : #endif
31 : :
32 : : #include <Python.h>
33 : : #include "pycore_pystate.h" // _PyThreadState_GET()
34 : : #include "complexobject.h"
35 : : #include "mpdecimal.h"
36 : :
37 : : #include <stdlib.h>
38 : :
39 : : #include "docstrings.h"
40 : :
41 : :
42 : : #if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02050000
43 : : #error "libmpdec version >= 2.5.0 required"
44 : : #endif
45 : :
46 : :
47 : : /*
48 : : * Type sizes with assertions in mpdecimal.h and pyport.h:
49 : : * sizeof(size_t) == sizeof(Py_ssize_t)
50 : : * sizeof(size_t) == sizeof(mpd_uint_t) == sizeof(mpd_ssize_t)
51 : : */
52 : :
53 : : #ifdef TEST_COVERAGE
54 : : #undef Py_LOCAL_INLINE
55 : : #define Py_LOCAL_INLINE Py_LOCAL
56 : : #endif
57 : :
58 : : #define MPD_Float_operation MPD_Not_implemented
59 : :
60 : : #define BOUNDS_CHECK(x, MIN, MAX) x = (x < MIN || MAX < x) ? MAX : x
61 : :
62 : : #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
63 : : #define UNUSED __attribute__((unused))
64 : : #else
65 : : #define UNUSED
66 : : #endif
67 : :
68 : : /* _Py_DEC_MINALLOC >= MPD_MINALLOC */
69 : : #define _Py_DEC_MINALLOC 4
70 : :
71 : : typedef struct {
72 : : PyObject_HEAD
73 : : Py_hash_t hash;
74 : : mpd_t dec;
75 : : mpd_uint_t data[_Py_DEC_MINALLOC];
76 : : } PyDecObject;
77 : :
78 : : typedef struct {
79 : : PyObject_HEAD
80 : : uint32_t *flags;
81 : : } PyDecSignalDictObject;
82 : :
83 : : typedef struct {
84 : : PyObject_HEAD
85 : : mpd_context_t ctx;
86 : : PyObject *traps;
87 : : PyObject *flags;
88 : : int capitals;
89 : : PyThreadState *tstate;
90 : : } PyDecContextObject;
91 : :
92 : : typedef struct {
93 : : PyObject_HEAD
94 : : PyObject *local;
95 : : PyObject *global;
96 : : } PyDecContextManagerObject;
97 : :
98 : :
99 : : #undef MPD
100 : : #undef CTX
101 : : static PyTypeObject PyDec_Type;
102 : : static PyTypeObject *PyDecSignalDict_Type;
103 : : static PyTypeObject PyDecContext_Type;
104 : : static PyTypeObject PyDecContextManager_Type;
105 : : #define PyDec_CheckExact(v) Py_IS_TYPE(v, &PyDec_Type)
106 : : #define PyDec_Check(v) PyObject_TypeCheck(v, &PyDec_Type)
107 : : #define PyDecSignalDict_Check(v) Py_IS_TYPE(v, PyDecSignalDict_Type)
108 : : #define PyDecContext_Check(v) PyObject_TypeCheck(v, &PyDecContext_Type)
109 : : #define MPD(v) (&((PyDecObject *)v)->dec)
110 : : #define SdFlagAddr(v) (((PyDecSignalDictObject *)v)->flags)
111 : : #define SdFlags(v) (*((PyDecSignalDictObject *)v)->flags)
112 : : #define CTX(v) (&((PyDecContextObject *)v)->ctx)
113 : : #define CtxCaps(v) (((PyDecContextObject *)v)->capitals)
114 : :
115 : :
116 : : Py_LOCAL_INLINE(PyObject *)
117 : 118311 : incr_true(void)
118 : : {
119 : 118311 : Py_INCREF(Py_True);
120 : 118311 : return Py_True;
121 : : }
122 : :
123 : : Py_LOCAL_INLINE(PyObject *)
124 : 608331 : incr_false(void)
125 : : {
126 : 608331 : Py_INCREF(Py_False);
127 : 608331 : return Py_False;
128 : : }
129 : :
130 : :
131 : : #ifndef WITH_DECIMAL_CONTEXTVAR
132 : : /* Key for thread state dictionary */
133 : : static PyObject *tls_context_key = NULL;
134 : : /* Invariant: NULL or the most recently accessed thread local context */
135 : : static PyDecContextObject *cached_context = NULL;
136 : : #else
137 : : static PyObject *current_context_var = NULL;
138 : : #endif
139 : :
140 : : /* Template for creating new thread contexts, calling Context() without
141 : : * arguments and initializing the module_context on first access. */
142 : : static PyObject *default_context_template = NULL;
143 : : /* Basic and extended context templates */
144 : : static PyObject *basic_context_template = NULL;
145 : : static PyObject *extended_context_template = NULL;
146 : :
147 : :
148 : : /* Error codes for functions that return signals or conditions */
149 : : #define DEC_INVALID_SIGNALS (MPD_Max_status+1U)
150 : : #define DEC_ERR_OCCURRED (DEC_INVALID_SIGNALS<<1)
151 : : #define DEC_ERRORS (DEC_INVALID_SIGNALS|DEC_ERR_OCCURRED)
152 : :
153 : : typedef struct {
154 : : const char *name; /* condition or signal name */
155 : : const char *fqname; /* fully qualified name */
156 : : uint32_t flag; /* libmpdec flag */
157 : : PyObject *ex; /* corresponding exception */
158 : : } DecCondMap;
159 : :
160 : : /* Top level Exception; inherits from ArithmeticError */
161 : : static PyObject *DecimalException = NULL;
162 : :
163 : : /* Exceptions that correspond to IEEE signals */
164 : : #define SUBNORMAL 5
165 : : #define INEXACT 6
166 : : #define ROUNDED 7
167 : : #define SIGNAL_MAP_LEN 9
168 : : static DecCondMap signal_map[] = {
169 : : {"InvalidOperation", "decimal.InvalidOperation", MPD_IEEE_Invalid_operation, NULL},
170 : : {"FloatOperation", "decimal.FloatOperation", MPD_Float_operation, NULL},
171 : : {"DivisionByZero", "decimal.DivisionByZero", MPD_Division_by_zero, NULL},
172 : : {"Overflow", "decimal.Overflow", MPD_Overflow, NULL},
173 : : {"Underflow", "decimal.Underflow", MPD_Underflow, NULL},
174 : : {"Subnormal", "decimal.Subnormal", MPD_Subnormal, NULL},
175 : : {"Inexact", "decimal.Inexact", MPD_Inexact, NULL},
176 : : {"Rounded", "decimal.Rounded", MPD_Rounded, NULL},
177 : : {"Clamped", "decimal.Clamped", MPD_Clamped, NULL},
178 : : {NULL}
179 : : };
180 : :
181 : : /* Exceptions that inherit from InvalidOperation */
182 : : static DecCondMap cond_map[] = {
183 : : {"InvalidOperation", "decimal.InvalidOperation", MPD_Invalid_operation, NULL},
184 : : {"ConversionSyntax", "decimal.ConversionSyntax", MPD_Conversion_syntax, NULL},
185 : : {"DivisionImpossible", "decimal.DivisionImpossible", MPD_Division_impossible, NULL},
186 : : {"DivisionUndefined", "decimal.DivisionUndefined", MPD_Division_undefined, NULL},
187 : : {"InvalidContext", "decimal.InvalidContext", MPD_Invalid_context, NULL},
188 : : #ifdef EXTRA_FUNCTIONALITY
189 : : {"MallocError", "decimal.MallocError", MPD_Malloc_error, NULL},
190 : : #endif
191 : : {NULL}
192 : : };
193 : :
194 : : static const char *dec_signal_string[MPD_NUM_FLAGS] = {
195 : : "Clamped",
196 : : "InvalidOperation",
197 : : "DivisionByZero",
198 : : "InvalidOperation",
199 : : "InvalidOperation",
200 : : "InvalidOperation",
201 : : "Inexact",
202 : : "InvalidOperation",
203 : : "InvalidOperation",
204 : : "InvalidOperation",
205 : : "FloatOperation",
206 : : "Overflow",
207 : : "Rounded",
208 : : "Subnormal",
209 : : "Underflow",
210 : : };
211 : :
212 : : #ifdef EXTRA_FUNCTIONALITY
213 : : #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
214 : : #else
215 : : #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
216 : : #endif
217 : : static PyObject *round_map[_PY_DEC_ROUND_GUARD];
218 : :
219 : : static const char *invalid_rounding_err =
220 : : "valid values for rounding are:\n\
221 : : [ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
222 : : ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,\n\
223 : : ROUND_05UP]";
224 : :
225 : : static const char *invalid_signals_err =
226 : : "valid values for signals are:\n\
227 : : [InvalidOperation, FloatOperation, DivisionByZero,\n\
228 : : Overflow, Underflow, Subnormal, Inexact, Rounded,\n\
229 : : Clamped]";
230 : :
231 : : #ifdef EXTRA_FUNCTIONALITY
232 : : static const char *invalid_flags_err =
233 : : "valid values for _flags or _traps are:\n\
234 : : signals:\n\
235 : : [DecIEEEInvalidOperation, DecFloatOperation, DecDivisionByZero,\n\
236 : : DecOverflow, DecUnderflow, DecSubnormal, DecInexact, DecRounded,\n\
237 : : DecClamped]\n\
238 : : conditions which trigger DecIEEEInvalidOperation:\n\
239 : : [DecInvalidOperation, DecConversionSyntax, DecDivisionImpossible,\n\
240 : : DecDivisionUndefined, DecFpuError, DecInvalidContext, DecMallocError]";
241 : : #endif
242 : :
243 : : static int
244 : 44 : value_error_int(const char *mesg)
245 : : {
246 : 44 : PyErr_SetString(PyExc_ValueError, mesg);
247 : 44 : return -1;
248 : : }
249 : :
250 : : #ifdef CONFIG_32
251 : : static PyObject *
252 : : value_error_ptr(const char *mesg)
253 : : {
254 : : PyErr_SetString(PyExc_ValueError, mesg);
255 : : return NULL;
256 : : }
257 : : #endif
258 : :
259 : : static int
260 : 19 : type_error_int(const char *mesg)
261 : : {
262 : 19 : PyErr_SetString(PyExc_TypeError, mesg);
263 : 19 : return -1;
264 : : }
265 : :
266 : : static int
267 : 0 : runtime_error_int(const char *mesg)
268 : : {
269 : 0 : PyErr_SetString(PyExc_RuntimeError, mesg);
270 : 0 : return -1;
271 : : }
272 : : #define INTERNAL_ERROR_INT(funcname) \
273 : : return runtime_error_int("internal error in " funcname)
274 : :
275 : : static PyObject *
276 : 0 : runtime_error_ptr(const char *mesg)
277 : : {
278 : 0 : PyErr_SetString(PyExc_RuntimeError, mesg);
279 : 0 : return NULL;
280 : : }
281 : : #define INTERNAL_ERROR_PTR(funcname) \
282 : : return runtime_error_ptr("internal error in " funcname)
283 : :
284 : : static void
285 : 0 : dec_traphandler(mpd_context_t *ctx UNUSED) /* GCOV_NOT_REACHED */
286 : : { /* GCOV_NOT_REACHED */
287 : 0 : return; /* GCOV_NOT_REACHED */
288 : : }
289 : :
290 : : static PyObject *
291 : 166 : flags_as_exception(uint32_t flags)
292 : : {
293 : : DecCondMap *cm;
294 : :
295 [ + - ]: 248 : for (cm = signal_map; cm->name != NULL; cm++) {
296 [ + + ]: 248 : if (flags&cm->flag) {
297 : 166 : return cm->ex;
298 : : }
299 : : }
300 : :
301 : 0 : INTERNAL_ERROR_PTR("flags_as_exception"); /* GCOV_NOT_REACHED */
302 : : }
303 : :
304 : : Py_LOCAL_INLINE(uint32_t)
305 : 1485377 : exception_as_flag(PyObject *ex)
306 : : {
307 : : DecCondMap *cm;
308 : :
309 [ + + ]: 7717181 : for (cm = signal_map; cm->name != NULL; cm++) {
310 [ + + ]: 7717177 : if (cm->ex == ex) {
311 : 1485373 : return cm->flag;
312 : : }
313 : : }
314 : :
315 : 4 : PyErr_SetString(PyExc_KeyError, invalid_signals_err);
316 : 4 : return DEC_INVALID_SIGNALS;
317 : : }
318 : :
319 : : static PyObject *
320 : 166 : flags_as_list(uint32_t flags)
321 : : {
322 : : PyObject *list;
323 : : DecCondMap *cm;
324 : :
325 : 166 : list = PyList_New(0);
326 [ - + ]: 166 : if (list == NULL) {
327 : 0 : return NULL;
328 : : }
329 : :
330 [ + + ]: 996 : for (cm = cond_map; cm->name != NULL; cm++) {
331 [ + + ]: 830 : if (flags&cm->flag) {
332 [ - + ]: 138 : if (PyList_Append(list, cm->ex) < 0) {
333 : 0 : goto error;
334 : : }
335 : : }
336 : : }
337 [ + + ]: 1494 : for (cm = signal_map+1; cm->name != NULL; cm++) {
338 [ + + ]: 1328 : if (flags&cm->flag) {
339 [ - + ]: 30 : if (PyList_Append(list, cm->ex) < 0) {
340 : 0 : goto error;
341 : : }
342 : : }
343 : : }
344 : :
345 : 166 : return list;
346 : :
347 : 0 : error:
348 : 0 : Py_DECREF(list);
349 : 0 : return NULL;
350 : : }
351 : :
352 : : static PyObject *
353 : 15564 : signals_as_list(uint32_t flags)
354 : : {
355 : : PyObject *list;
356 : : DecCondMap *cm;
357 : :
358 : 15564 : list = PyList_New(0);
359 [ - + ]: 15564 : if (list == NULL) {
360 : 0 : return NULL;
361 : : }
362 : :
363 [ + + ]: 155640 : for (cm = signal_map; cm->name != NULL; cm++) {
364 [ + + ]: 140076 : if (flags&cm->flag) {
365 [ - + ]: 62226 : if (PyList_Append(list, cm->ex) < 0) {
366 : 0 : Py_DECREF(list);
367 : 0 : return NULL;
368 : : }
369 : : }
370 : : }
371 : :
372 : 15564 : return list;
373 : : }
374 : :
375 : : static uint32_t
376 : 31123 : list_as_flags(PyObject *list)
377 : : {
378 : : PyObject *item;
379 : : uint32_t flags, x;
380 : : Py_ssize_t n, j;
381 : :
382 : : assert(PyList_Check(list));
383 : :
384 : 31123 : n = PyList_Size(list);
385 : 31123 : flags = 0;
386 [ + + ]: 155561 : for (j = 0; j < n; j++) {
387 : 124440 : item = PyList_GetItem(list, j);
388 : 124440 : x = exception_as_flag(item);
389 [ + + ]: 124440 : if (x & DEC_ERRORS) {
390 : 2 : return x;
391 : : }
392 : 124438 : flags |= x;
393 : : }
394 : :
395 : 31121 : return flags;
396 : : }
397 : :
398 : : static PyObject *
399 : 1 : flags_as_dict(uint32_t flags)
400 : : {
401 : : DecCondMap *cm;
402 : : PyObject *dict;
403 : :
404 : 1 : dict = PyDict_New();
405 [ - + ]: 1 : if (dict == NULL) {
406 : 0 : return NULL;
407 : : }
408 : :
409 [ + + ]: 10 : for (cm = signal_map; cm->name != NULL; cm++) {
410 [ - + ]: 9 : PyObject *b = flags&cm->flag ? Py_True : Py_False;
411 [ - + ]: 9 : if (PyDict_SetItem(dict, cm->ex, b) < 0) {
412 : 0 : Py_DECREF(dict);
413 : 0 : return NULL;
414 : : }
415 : : }
416 : :
417 : 1 : return dict;
418 : : }
419 : :
420 : : static uint32_t
421 : 24 : dict_as_flags(PyObject *val)
422 : : {
423 : : PyObject *b;
424 : : DecCondMap *cm;
425 : 24 : uint32_t flags = 0;
426 : : int x;
427 : :
428 [ + + ]: 24 : if (!PyDict_Check(val)) {
429 : 9 : PyErr_SetString(PyExc_TypeError,
430 : : "argument must be a signal dict");
431 : 9 : return DEC_INVALID_SIGNALS;
432 : : }
433 : :
434 [ + + ]: 15 : if (PyDict_Size(val) != SIGNAL_MAP_LEN) {
435 : 6 : PyErr_SetString(PyExc_KeyError,
436 : : "invalid signal dict");
437 : 6 : return DEC_INVALID_SIGNALS;
438 : : }
439 : :
440 [ + + ]: 74 : for (cm = signal_map; cm->name != NULL; cm++) {
441 : 67 : b = PyDict_GetItemWithError(val, cm->ex);
442 [ + + ]: 67 : if (b == NULL) {
443 [ - + ]: 2 : if (PyErr_Occurred()) {
444 : 0 : return DEC_ERR_OCCURRED;
445 : : }
446 : 2 : PyErr_SetString(PyExc_KeyError,
447 : : "invalid signal dict");
448 : 2 : return DEC_INVALID_SIGNALS;
449 : : }
450 : :
451 : 65 : x = PyObject_IsTrue(b);
452 [ - + ]: 65 : if (x < 0) {
453 : 0 : return DEC_ERR_OCCURRED;
454 : : }
455 [ + + ]: 65 : if (x == 1) {
456 : 22 : flags |= cm->flag;
457 : : }
458 : : }
459 : :
460 : 7 : return flags;
461 : : }
462 : :
463 : : #ifdef EXTRA_FUNCTIONALITY
464 : : static uint32_t
465 : : long_as_flags(PyObject *v)
466 : : {
467 : : long x;
468 : :
469 : : x = PyLong_AsLong(v);
470 : : if (x == -1 && PyErr_Occurred()) {
471 : : return DEC_ERR_OCCURRED;
472 : : }
473 : : if (x < 0 || x > (long)MPD_Max_status) {
474 : : PyErr_SetString(PyExc_TypeError, invalid_flags_err);
475 : : return DEC_INVALID_SIGNALS;
476 : : }
477 : :
478 : : return x;
479 : : }
480 : : #endif
481 : :
482 : : static int
483 : 375967 : dec_addstatus(PyObject *context, uint32_t status)
484 : : {
485 : 375967 : mpd_context_t *ctx = CTX(context);
486 : :
487 : 375967 : ctx->status |= status;
488 [ + + ]: 375967 : if (status & (ctx->traps|MPD_Malloc_error)) {
489 : : PyObject *ex, *siglist;
490 : :
491 [ - + ]: 166 : if (status & MPD_Malloc_error) {
492 : : PyErr_NoMemory();
493 : 0 : return 1;
494 : : }
495 : :
496 : 166 : ex = flags_as_exception(ctx->traps&status);
497 [ - + ]: 166 : if (ex == NULL) {
498 : 0 : return 1; /* GCOV_NOT_REACHED */
499 : : }
500 : 166 : siglist = flags_as_list(ctx->traps&status);
501 [ - + ]: 166 : if (siglist == NULL) {
502 : 0 : return 1;
503 : : }
504 : :
505 : 166 : PyErr_SetObject(ex, siglist);
506 : 166 : Py_DECREF(siglist);
507 : 166 : return 1;
508 : : }
509 : 375801 : return 0;
510 : : }
511 : :
512 : : static int
513 : 17452 : getround(PyObject *v)
514 : : {
515 : : int i;
516 : :
517 [ + + ]: 17452 : if (PyUnicode_Check(v)) {
518 [ + + ]: 111208 : for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
519 [ + + ]: 103419 : if (v == round_map[i]) {
520 : 9651 : return i;
521 : : }
522 : : }
523 [ + + ]: 35097 : for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
524 [ + + ]: 35090 : if (PyUnicode_Compare(v, round_map[i]) == 0) {
525 : 7782 : return i;
526 : : }
527 : : }
528 : : }
529 : :
530 : 19 : return type_error_int(invalid_rounding_err);
531 : : }
532 : :
533 : :
534 : : /******************************************************************************/
535 : : /* SignalDict Object */
536 : : /******************************************************************************/
537 : :
538 : : /* The SignalDict is a MutableMapping that provides access to the
539 : : mpd_context_t flags, which reside in the context object. When a
540 : : new context is created, context.traps and context.flags are
541 : : initialized to new SignalDicts. Once a SignalDict is tied to
542 : : a context, it cannot be deleted. */
543 : :
544 : : static int
545 : 32778 : signaldict_init(PyObject *self, PyObject *args UNUSED, PyObject *kwds UNUSED)
546 : : {
547 : 32778 : SdFlagAddr(self) = NULL;
548 : 32778 : return 0;
549 : : }
550 : :
551 : : static Py_ssize_t
552 : 1 : signaldict_len(PyObject *self UNUSED)
553 : : {
554 : 1 : return SIGNAL_MAP_LEN;
555 : : }
556 : :
557 : : static PyObject *SignalTuple;
558 : : static PyObject *
559 : 15597 : signaldict_iter(PyObject *self UNUSED)
560 : : {
561 : 15597 : return PyTuple_Type.tp_iter(SignalTuple);
562 : : }
563 : :
564 : : static PyObject *
565 : 723325 : signaldict_getitem(PyObject *self, PyObject *key)
566 : : {
567 : : uint32_t flag;
568 : :
569 : 723325 : flag = exception_as_flag(key);
570 [ - + ]: 723325 : if (flag & DEC_ERRORS) {
571 : 0 : return NULL;
572 : : }
573 : :
574 [ + + ]: 723325 : return SdFlags(self)&flag ? incr_true() : incr_false();
575 : : }
576 : :
577 : : static int
578 : 637614 : signaldict_setitem(PyObject *self, PyObject *key, PyObject *value)
579 : : {
580 : : uint32_t flag;
581 : : int x;
582 : :
583 [ + + ]: 637614 : if (value == NULL) {
584 : 2 : return value_error_int("signal keys cannot be deleted");
585 : : }
586 : :
587 : 637612 : flag = exception_as_flag(key);
588 [ + + ]: 637612 : if (flag & DEC_ERRORS) {
589 : 2 : return -1;
590 : : }
591 : :
592 : 637610 : x = PyObject_IsTrue(value);
593 [ - + ]: 637610 : if (x < 0) {
594 : 0 : return -1;
595 : : }
596 : :
597 [ + + ]: 637610 : if (x == 1) {
598 : 582831 : SdFlags(self) |= flag;
599 : : }
600 : : else {
601 : 54779 : SdFlags(self) &= ~flag;
602 : : }
603 : :
604 : 637610 : return 0;
605 : : }
606 : :
607 : : static PyObject *
608 : 0 : signaldict_repr(PyObject *self)
609 : : {
610 : : DecCondMap *cm;
611 : : const char *n[SIGNAL_MAP_LEN]; /* name */
612 : : const char *b[SIGNAL_MAP_LEN]; /* bool */
613 : : int i;
614 : :
615 : : assert(SIGNAL_MAP_LEN == 9);
616 : :
617 [ # # ]: 0 : for (cm=signal_map, i=0; cm->name != NULL; cm++, i++) {
618 : 0 : n[i] = cm->fqname;
619 [ # # ]: 0 : b[i] = SdFlags(self)&cm->flag ? "True" : "False";
620 : : }
621 : 0 : return PyUnicode_FromFormat(
622 : : "{<class '%s'>:%s, <class '%s'>:%s, <class '%s'>:%s, "
623 : : "<class '%s'>:%s, <class '%s'>:%s, <class '%s'>:%s, "
624 : : "<class '%s'>:%s, <class '%s'>:%s, <class '%s'>:%s}",
625 : : n[0], b[0], n[1], b[1], n[2], b[2],
626 : : n[3], b[3], n[4], b[4], n[5], b[5],
627 : : n[6], b[6], n[7], b[7], n[8], b[8]);
628 : : }
629 : :
630 : : static PyObject *
631 : 33 : signaldict_richcompare(PyObject *v, PyObject *w, int op)
632 : : {
633 : 33 : PyObject *res = Py_NotImplemented;
634 : :
635 : : assert(PyDecSignalDict_Check(v));
636 : :
637 [ + + + - ]: 33 : if (op == Py_EQ || op == Py_NE) {
638 [ + + ]: 33 : if (PyDecSignalDict_Check(w)) {
639 [ + - ]: 25 : res = (SdFlags(v)==SdFlags(w)) ^ (op==Py_NE) ? Py_True : Py_False;
640 : : }
641 [ + + ]: 8 : else if (PyDict_Check(w)) {
642 : 6 : uint32_t flags = dict_as_flags(w);
643 [ + + ]: 6 : if (flags & DEC_ERRORS) {
644 [ + - ]: 2 : if (flags & DEC_INVALID_SIGNALS) {
645 : : /* non-comparable: Py_NotImplemented */
646 : 2 : PyErr_Clear();
647 : : }
648 : : else {
649 : 0 : return NULL;
650 : : }
651 : : }
652 : : else {
653 [ + - ]: 4 : res = (SdFlags(v)==flags) ^ (op==Py_NE) ? Py_True : Py_False;
654 : : }
655 : : }
656 : : }
657 : :
658 : 33 : Py_INCREF(res);
659 : 33 : return res;
660 : : }
661 : :
662 : : static PyObject *
663 : 1 : signaldict_copy(PyObject *self, PyObject *args UNUSED)
664 : : {
665 : 1 : return flags_as_dict(SdFlags(self));
666 : : }
667 : :
668 : :
669 : : static PyMappingMethods signaldict_as_mapping = {
670 : : (lenfunc)signaldict_len, /* mp_length */
671 : : (binaryfunc)signaldict_getitem, /* mp_subscript */
672 : : (objobjargproc)signaldict_setitem /* mp_ass_subscript */
673 : : };
674 : :
675 : : static PyMethodDef signaldict_methods[] = {
676 : : { "copy", (PyCFunction)signaldict_copy, METH_NOARGS, NULL},
677 : : {NULL, NULL}
678 : : };
679 : :
680 : :
681 : : static PyTypeObject PyDecSignalDictMixin_Type =
682 : : {
683 : : PyVarObject_HEAD_INIT(0, 0)
684 : : "decimal.SignalDictMixin", /* tp_name */
685 : : sizeof(PyDecSignalDictObject), /* tp_basicsize */
686 : : 0, /* tp_itemsize */
687 : : 0, /* tp_dealloc */
688 : : 0, /* tp_vectorcall_offset */
689 : : (getattrfunc) 0, /* tp_getattr */
690 : : (setattrfunc) 0, /* tp_setattr */
691 : : 0, /* tp_as_async */
692 : : (reprfunc) signaldict_repr, /* tp_repr */
693 : : 0, /* tp_as_number */
694 : : 0, /* tp_as_sequence */
695 : : &signaldict_as_mapping, /* tp_as_mapping */
696 : : PyObject_HashNotImplemented, /* tp_hash */
697 : : 0, /* tp_call */
698 : : (reprfunc) 0, /* tp_str */
699 : : PyObject_GenericGetAttr, /* tp_getattro */
700 : : (setattrofunc) 0, /* tp_setattro */
701 : : (PyBufferProcs *) 0, /* tp_as_buffer */
702 : : Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
703 : : 0, /* tp_doc */
704 : : 0, /* tp_traverse */
705 : : 0, /* tp_clear */
706 : : signaldict_richcompare, /* tp_richcompare */
707 : : 0, /* tp_weaklistoffset */
708 : : (getiterfunc)signaldict_iter, /* tp_iter */
709 : : 0, /* tp_iternext */
710 : : signaldict_methods, /* tp_methods */
711 : : 0, /* tp_members */
712 : : 0, /* tp_getset */
713 : : 0, /* tp_base */
714 : : 0, /* tp_dict */
715 : : 0, /* tp_descr_get */
716 : : 0, /* tp_descr_set */
717 : : 0, /* tp_dictoffset */
718 : : (initproc)signaldict_init, /* tp_init */
719 : : 0, /* tp_alloc */
720 : : PyType_GenericNew, /* tp_new */
721 : : };
722 : :
723 : :
724 : : /******************************************************************************/
725 : : /* Context Object, Part 1 */
726 : : /******************************************************************************/
727 : :
728 : : #define Dec_CONTEXT_GET_SSIZE(mem) \
729 : : static PyObject * \
730 : : context_get##mem(PyObject *self, void *closure UNUSED) \
731 : : { \
732 : : return PyLong_FromSsize_t(mpd_get##mem(CTX(self))); \
733 : : }
734 : :
735 : : #define Dec_CONTEXT_GET_ULONG(mem) \
736 : : static PyObject * \
737 : : context_get##mem(PyObject *self, void *closure UNUSED) \
738 : : { \
739 : : return PyLong_FromUnsignedLong(mpd_get##mem(CTX(self))); \
740 : : }
741 : :
742 : 7820 : Dec_CONTEXT_GET_SSIZE(prec)
743 : 7798 : Dec_CONTEXT_GET_SSIZE(emax)
744 : 7800 : Dec_CONTEXT_GET_SSIZE(emin)
745 : 7795 : Dec_CONTEXT_GET_SSIZE(clamp)
746 : :
747 : : #ifdef EXTRA_FUNCTIONALITY
748 : : Dec_CONTEXT_GET_ULONG(traps)
749 : : Dec_CONTEXT_GET_ULONG(status)
750 : : #endif
751 : :
752 : : static PyObject *
753 : 7795 : context_getround(PyObject *self, void *closure UNUSED)
754 : : {
755 : 7795 : int i = mpd_getround(CTX(self));
756 : :
757 : 7795 : Py_INCREF(round_map[i]);
758 : 7795 : return round_map[i];
759 : : }
760 : :
761 : : static PyObject *
762 : 7795 : context_getcapitals(PyObject *self, void *closure UNUSED)
763 : : {
764 : 7795 : return PyLong_FromLong(CtxCaps(self));
765 : : }
766 : :
767 : : #ifdef EXTRA_FUNCTIONALITY
768 : : static PyObject *
769 : : context_getallcr(PyObject *self, void *closure UNUSED)
770 : : {
771 : : return PyLong_FromLong(mpd_getcr(CTX(self)));
772 : : }
773 : : #endif
774 : :
775 : : static PyObject *
776 : 2 : context_getetiny(PyObject *self, PyObject *dummy UNUSED)
777 : : {
778 : 2 : return PyLong_FromSsize_t(mpd_etiny(CTX(self)));
779 : : }
780 : :
781 : : static PyObject *
782 : 2 : context_getetop(PyObject *self, PyObject *dummy UNUSED)
783 : : {
784 : 2 : return PyLong_FromSsize_t(mpd_etop(CTX(self)));
785 : : }
786 : :
787 : : static int
788 : 16920 : context_setprec(PyObject *self, PyObject *value, void *closure UNUSED)
789 : : {
790 : : mpd_context_t *ctx;
791 : : mpd_ssize_t x;
792 : :
793 : 16920 : x = PyLong_AsSsize_t(value);
794 [ + + + + ]: 16920 : if (x == -1 && PyErr_Occurred()) {
795 : 4 : return -1;
796 : : }
797 : :
798 : 16916 : ctx = CTX(self);
799 [ + + ]: 16916 : if (!mpd_qsetprec(ctx, x)) {
800 : 6 : return value_error_int(
801 : : "valid range for prec is [1, MAX_PREC]");
802 : : }
803 : :
804 : 16910 : return 0;
805 : : }
806 : :
807 : : static int
808 : 15999 : context_setemin(PyObject *self, PyObject *value, void *closure UNUSED)
809 : : {
810 : : mpd_context_t *ctx;
811 : : mpd_ssize_t x;
812 : :
813 : 15999 : x = PyLong_AsSsize_t(value);
814 [ + + + + ]: 15999 : if (x == -1 && PyErr_Occurred()) {
815 : 5 : return -1;
816 : : }
817 : :
818 : 15994 : ctx = CTX(self);
819 [ + + ]: 15994 : if (!mpd_qsetemin(ctx, x)) {
820 : 7 : return value_error_int(
821 : : "valid range for Emin is [MIN_EMIN, 0]");
822 : : }
823 : :
824 : 15987 : return 0;
825 : : }
826 : :
827 : : static int
828 : 16004 : context_setemax(PyObject *self, PyObject *value, void *closure UNUSED)
829 : : {
830 : : mpd_context_t *ctx;
831 : : mpd_ssize_t x;
832 : :
833 : 16004 : x = PyLong_AsSsize_t(value);
834 [ + + + + ]: 16004 : if (x == -1 && PyErr_Occurred()) {
835 : 5 : return -1;
836 : : }
837 : :
838 : 15999 : ctx = CTX(self);
839 [ + + ]: 15999 : if (!mpd_qsetemax(ctx, x)) {
840 : 7 : return value_error_int(
841 : : "valid range for Emax is [0, MAX_EMAX]");
842 : : }
843 : :
844 : 15992 : return 0;
845 : : }
846 : :
847 : : #ifdef CONFIG_32
848 : : static PyObject *
849 : : context_unsafe_setprec(PyObject *self, PyObject *value)
850 : : {
851 : : mpd_context_t *ctx = CTX(self);
852 : : mpd_ssize_t x;
853 : :
854 : : x = PyLong_AsSsize_t(value);
855 : : if (x == -1 && PyErr_Occurred()) {
856 : : return NULL;
857 : : }
858 : :
859 : : if (x < 1 || x > 1070000000L) {
860 : : return value_error_ptr(
861 : : "valid range for unsafe prec is [1, 1070000000]");
862 : : }
863 : :
864 : : ctx->prec = x;
865 : : Py_RETURN_NONE;
866 : : }
867 : :
868 : : static PyObject *
869 : : context_unsafe_setemin(PyObject *self, PyObject *value)
870 : : {
871 : : mpd_context_t *ctx = CTX(self);
872 : : mpd_ssize_t x;
873 : :
874 : : x = PyLong_AsSsize_t(value);
875 : : if (x == -1 && PyErr_Occurred()) {
876 : : return NULL;
877 : : }
878 : :
879 : : if (x < -1070000000L || x > 0) {
880 : : return value_error_ptr(
881 : : "valid range for unsafe emin is [-1070000000, 0]");
882 : : }
883 : :
884 : : ctx->emin = x;
885 : : Py_RETURN_NONE;
886 : : }
887 : :
888 : : static PyObject *
889 : : context_unsafe_setemax(PyObject *self, PyObject *value)
890 : : {
891 : : mpd_context_t *ctx = CTX(self);
892 : : mpd_ssize_t x;
893 : :
894 : : x = PyLong_AsSsize_t(value);
895 : : if (x == -1 && PyErr_Occurred()) {
896 : : return NULL;
897 : : }
898 : :
899 : : if (x < 0 || x > 1070000000L) {
900 : : return value_error_ptr(
901 : : "valid range for unsafe emax is [0, 1070000000]");
902 : : }
903 : :
904 : : ctx->emax = x;
905 : : Py_RETURN_NONE;
906 : : }
907 : : #endif
908 : :
909 : : static int
910 : 16428 : context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
911 : : {
912 : : mpd_context_t *ctx;
913 : : int x;
914 : :
915 : 16428 : x = getround(value);
916 [ + + ]: 16428 : if (x == -1) {
917 : 9 : return -1;
918 : : }
919 : :
920 : 16419 : ctx = CTX(self);
921 [ - + ]: 16419 : if (!mpd_qsetround(ctx, x)) {
922 : 0 : INTERNAL_ERROR_INT("context_setround"); /* GCOV_NOT_REACHED */
923 : : }
924 : :
925 : 16419 : return 0;
926 : : }
927 : :
928 : : static int
929 : 15582 : context_setcapitals(PyObject *self, PyObject *value, void *closure UNUSED)
930 : : {
931 : : mpd_ssize_t x;
932 : :
933 : 15582 : x = PyLong_AsSsize_t(value);
934 [ + + + + ]: 15582 : if (x == -1 && PyErr_Occurred()) {
935 : 5 : return -1;
936 : : }
937 : :
938 [ + + + + ]: 15577 : if (x != 0 && x != 1) {
939 : 11 : return value_error_int(
940 : : "valid values for capitals are 0 or 1");
941 : : }
942 : 15566 : CtxCaps(self) = (int)x;
943 : :
944 : 15566 : return 0;
945 : : }
946 : :
947 : : #ifdef EXTRA_FUNCTIONALITY
948 : : static int
949 : : context_settraps(PyObject *self, PyObject *value, void *closure UNUSED)
950 : : {
951 : : mpd_context_t *ctx;
952 : : uint32_t flags;
953 : :
954 : : flags = long_as_flags(value);
955 : : if (flags & DEC_ERRORS) {
956 : : return -1;
957 : : }
958 : :
959 : : ctx = CTX(self);
960 : : if (!mpd_qsettraps(ctx, flags)) {
961 : : INTERNAL_ERROR_INT("context_settraps");
962 : : }
963 : :
964 : : return 0;
965 : : }
966 : : #endif
967 : :
968 : : static int
969 : 15562 : context_settraps_list(PyObject *self, PyObject *value)
970 : : {
971 : : mpd_context_t *ctx;
972 : : uint32_t flags;
973 : :
974 : 15562 : flags = list_as_flags(value);
975 [ + + ]: 15562 : if (flags & DEC_ERRORS) {
976 : 1 : return -1;
977 : : }
978 : :
979 : 15561 : ctx = CTX(self);
980 [ - + ]: 15561 : if (!mpd_qsettraps(ctx, flags)) {
981 : 0 : INTERNAL_ERROR_INT("context_settraps_list");
982 : : }
983 : :
984 : 15561 : return 0;
985 : : }
986 : :
987 : : static int
988 : 10 : context_settraps_dict(PyObject *self, PyObject *value)
989 : : {
990 : : mpd_context_t *ctx;
991 : : uint32_t flags;
992 : :
993 [ + + ]: 10 : if (PyDecSignalDict_Check(value)) {
994 : 1 : flags = SdFlags(value);
995 : : }
996 : : else {
997 : 9 : flags = dict_as_flags(value);
998 [ + + ]: 9 : if (flags & DEC_ERRORS) {
999 : 7 : return -1;
1000 : : }
1001 : : }
1002 : :
1003 : 3 : ctx = CTX(self);
1004 [ - + ]: 3 : if (!mpd_qsettraps(ctx, flags)) {
1005 : 0 : INTERNAL_ERROR_INT("context_settraps_dict");
1006 : : }
1007 : :
1008 : 3 : return 0;
1009 : : }
1010 : :
1011 : : #ifdef EXTRA_FUNCTIONALITY
1012 : : static int
1013 : : context_setstatus(PyObject *self, PyObject *value, void *closure UNUSED)
1014 : : {
1015 : : mpd_context_t *ctx;
1016 : : uint32_t flags;
1017 : :
1018 : : flags = long_as_flags(value);
1019 : : if (flags & DEC_ERRORS) {
1020 : : return -1;
1021 : : }
1022 : :
1023 : : ctx = CTX(self);
1024 : : if (!mpd_qsetstatus(ctx, flags)) {
1025 : : INTERNAL_ERROR_INT("context_setstatus");
1026 : : }
1027 : :
1028 : : return 0;
1029 : : }
1030 : : #endif
1031 : :
1032 : : static int
1033 : 15561 : context_setstatus_list(PyObject *self, PyObject *value)
1034 : : {
1035 : : mpd_context_t *ctx;
1036 : : uint32_t flags;
1037 : :
1038 : 15561 : flags = list_as_flags(value);
1039 [ + + ]: 15561 : if (flags & DEC_ERRORS) {
1040 : 1 : return -1;
1041 : : }
1042 : :
1043 : 15560 : ctx = CTX(self);
1044 [ - + ]: 15560 : if (!mpd_qsetstatus(ctx, flags)) {
1045 : 0 : INTERNAL_ERROR_INT("context_setstatus_list");
1046 : : }
1047 : :
1048 : 15560 : return 0;
1049 : : }
1050 : :
1051 : : static int
1052 : 10 : context_setstatus_dict(PyObject *self, PyObject *value)
1053 : : {
1054 : : mpd_context_t *ctx;
1055 : : uint32_t flags;
1056 : :
1057 [ + + ]: 10 : if (PyDecSignalDict_Check(value)) {
1058 : 1 : flags = SdFlags(value);
1059 : : }
1060 : : else {
1061 : 9 : flags = dict_as_flags(value);
1062 [ + + ]: 9 : if (flags & DEC_ERRORS) {
1063 : 8 : return -1;
1064 : : }
1065 : : }
1066 : :
1067 : 2 : ctx = CTX(self);
1068 [ - + ]: 2 : if (!mpd_qsetstatus(ctx, flags)) {
1069 : 0 : INTERNAL_ERROR_INT("context_setstatus_dict");
1070 : : }
1071 : :
1072 : 2 : return 0;
1073 : : }
1074 : :
1075 : : static int
1076 : 15685 : context_setclamp(PyObject *self, PyObject *value, void *closure UNUSED)
1077 : : {
1078 : : mpd_context_t *ctx;
1079 : : mpd_ssize_t x;
1080 : :
1081 : 15685 : x = PyLong_AsSsize_t(value);
1082 [ + + + + ]: 15685 : if (x == -1 && PyErr_Occurred()) {
1083 : 5 : return -1;
1084 : : }
1085 [ + + + + ]: 15680 : BOUNDS_CHECK(x, INT_MIN, INT_MAX);
1086 : :
1087 : 15680 : ctx = CTX(self);
1088 [ + + ]: 15680 : if (!mpd_qsetclamp(ctx, (int)x)) {
1089 : 11 : return value_error_int("valid values for clamp are 0 or 1");
1090 : : }
1091 : :
1092 : 15669 : return 0;
1093 : : }
1094 : :
1095 : : #ifdef EXTRA_FUNCTIONALITY
1096 : : static int
1097 : : context_setallcr(PyObject *self, PyObject *value, void *closure UNUSED)
1098 : : {
1099 : : mpd_context_t *ctx;
1100 : : mpd_ssize_t x;
1101 : :
1102 : : x = PyLong_AsSsize_t(value);
1103 : : if (x == -1 && PyErr_Occurred()) {
1104 : : return -1;
1105 : : }
1106 : : BOUNDS_CHECK(x, INT_MIN, INT_MAX);
1107 : :
1108 : : ctx = CTX(self);
1109 : : if (!mpd_qsetcr(ctx, (int)x)) {
1110 : : return value_error_int("valid values for _allcr are 0 or 1");
1111 : : }
1112 : :
1113 : : return 0;
1114 : : }
1115 : : #endif
1116 : :
1117 : : static PyObject *
1118 : 1433526 : context_getattr(PyObject *self, PyObject *name)
1119 : : {
1120 : : PyObject *retval;
1121 : :
1122 [ + - ]: 1433526 : if (PyUnicode_Check(name)) {
1123 [ + + ]: 1433526 : if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) {
1124 : 645416 : retval = ((PyDecContextObject *)self)->traps;
1125 : 645416 : Py_INCREF(retval);
1126 : 645416 : return retval;
1127 : : }
1128 [ + + ]: 788110 : if (PyUnicode_CompareWithASCIIString(name, "flags") == 0) {
1129 : 590839 : retval = ((PyDecContextObject *)self)->flags;
1130 : 590839 : Py_INCREF(retval);
1131 : 590839 : return retval;
1132 : : }
1133 : : }
1134 : :
1135 : 197271 : return PyObject_GenericGetAttr(self, name);
1136 : : }
1137 : :
1138 : : static int
1139 : 3168 : context_setattr(PyObject *self, PyObject *name, PyObject *value)
1140 : : {
1141 [ + + ]: 3168 : if (value == NULL) {
1142 : 8 : PyErr_SetString(PyExc_AttributeError,
1143 : : "context attributes cannot be deleted");
1144 : 8 : return -1;
1145 : : }
1146 : :
1147 [ + - ]: 3160 : if (PyUnicode_Check(name)) {
1148 [ + + ]: 3160 : if (PyUnicode_CompareWithASCIIString(name, "traps") == 0) {
1149 : 7 : return context_settraps_dict(self, value);
1150 : : }
1151 [ + + ]: 3153 : if (PyUnicode_CompareWithASCIIString(name, "flags") == 0) {
1152 : 8 : return context_setstatus_dict(self, value);
1153 : : }
1154 : : }
1155 : :
1156 : 3145 : return PyObject_GenericSetAttr(self, name, value);
1157 : : }
1158 : :
1159 : : static int
1160 : 16548 : context_setattrs(PyObject *self, PyObject *prec, PyObject *rounding,
1161 : : PyObject *emin, PyObject *emax, PyObject *capitals,
1162 : : PyObject *clamp, PyObject *status, PyObject *traps) {
1163 : :
1164 : : int ret;
1165 [ + + + + ]: 16548 : if (prec != Py_None && context_setprec(self, prec, NULL) < 0) {
1166 : 2 : return -1;
1167 : : }
1168 [ + + + + ]: 16546 : if (rounding != Py_None && context_setround(self, rounding, NULL) < 0) {
1169 : 4 : return -1;
1170 : : }
1171 [ + + + + ]: 16542 : if (emin != Py_None && context_setemin(self, emin, NULL) < 0) {
1172 : 4 : return -1;
1173 : : }
1174 [ + + + + ]: 16538 : if (emax != Py_None && context_setemax(self, emax, NULL) < 0) {
1175 : 4 : return -1;
1176 : : }
1177 [ + + + + ]: 16534 : if (capitals != Py_None && context_setcapitals(self, capitals, NULL) < 0) {
1178 : 3 : return -1;
1179 : : }
1180 [ + + + + ]: 16531 : if (clamp != Py_None && context_setclamp(self, clamp, NULL) < 0) {
1181 : 3 : return -1;
1182 : : }
1183 : :
1184 [ + + ]: 16528 : if (traps != Py_None) {
1185 [ + + ]: 15565 : if (PyList_Check(traps)) {
1186 : 15562 : ret = context_settraps_list(self, traps);
1187 : : }
1188 : : #ifdef EXTRA_FUNCTIONALITY
1189 : : else if (PyLong_Check(traps)) {
1190 : : ret = context_settraps(self, traps, NULL);
1191 : : }
1192 : : #endif
1193 : : else {
1194 : 3 : ret = context_settraps_dict(self, traps);
1195 : : }
1196 [ + + ]: 15565 : if (ret < 0) {
1197 : 3 : return ret;
1198 : : }
1199 : : }
1200 [ + + ]: 16525 : if (status != Py_None) {
1201 [ + + ]: 15563 : if (PyList_Check(status)) {
1202 : 15561 : ret = context_setstatus_list(self, status);
1203 : : }
1204 : : #ifdef EXTRA_FUNCTIONALITY
1205 : : else if (PyLong_Check(status)) {
1206 : : ret = context_setstatus(self, status, NULL);
1207 : : }
1208 : : #endif
1209 : : else {
1210 : 2 : ret = context_setstatus_dict(self, status);
1211 : : }
1212 [ + + ]: 15563 : if (ret < 0) {
1213 : 3 : return ret;
1214 : : }
1215 : : }
1216 : :
1217 : 16522 : return 0;
1218 : : }
1219 : :
1220 : : static PyObject *
1221 : 4 : context_clear_traps(PyObject *self, PyObject *dummy UNUSED)
1222 : : {
1223 : 4 : CTX(self)->traps = 0;
1224 : 4 : Py_RETURN_NONE;
1225 : : }
1226 : :
1227 : : static PyObject *
1228 : 65534 : context_clear_flags(PyObject *self, PyObject *dummy UNUSED)
1229 : : {
1230 : 65534 : CTX(self)->status = 0;
1231 : 65534 : Py_RETURN_NONE;
1232 : : }
1233 : :
1234 : : #define DEC_DFLT_EMAX 999999
1235 : : #define DEC_DFLT_EMIN -999999
1236 : :
1237 : : static mpd_context_t dflt_ctx = {
1238 : : 28, DEC_DFLT_EMAX, DEC_DFLT_EMIN,
1239 : : MPD_IEEE_Invalid_operation|MPD_Division_by_zero|MPD_Overflow,
1240 : : 0, 0, MPD_ROUND_HALF_EVEN, 0, 1
1241 : : };
1242 : :
1243 : : static PyObject *
1244 : 16389 : context_new(PyTypeObject *type, PyObject *args UNUSED, PyObject *kwds UNUSED)
1245 : : {
1246 : 16389 : PyDecContextObject *self = NULL;
1247 : : mpd_context_t *ctx;
1248 : :
1249 [ + + ]: 16389 : if (type == &PyDecContext_Type) {
1250 : 16372 : self = PyObject_New(PyDecContextObject, &PyDecContext_Type);
1251 : : }
1252 : : else {
1253 : 17 : self = (PyDecContextObject *)type->tp_alloc(type, 0);
1254 : : }
1255 : :
1256 [ - + ]: 16389 : if (self == NULL) {
1257 : 0 : return NULL;
1258 : : }
1259 : :
1260 : 16389 : self->traps = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL);
1261 [ - + ]: 16389 : if (self->traps == NULL) {
1262 : 0 : self->flags = NULL;
1263 : 0 : Py_DECREF(self);
1264 : 0 : return NULL;
1265 : : }
1266 : 16389 : self->flags = PyObject_CallObject((PyObject *)PyDecSignalDict_Type, NULL);
1267 [ - + ]: 16389 : if (self->flags == NULL) {
1268 : 0 : Py_DECREF(self);
1269 : 0 : return NULL;
1270 : : }
1271 : :
1272 : 16389 : ctx = CTX(self);
1273 : :
1274 [ + + ]: 16389 : if (default_context_template) {
1275 : 16339 : *ctx = *CTX(default_context_template);
1276 : : }
1277 : : else {
1278 : 50 : *ctx = dflt_ctx;
1279 : : }
1280 : :
1281 : 16389 : SdFlagAddr(self->traps) = &ctx->traps;
1282 : 16389 : SdFlagAddr(self->flags) = &ctx->status;
1283 : :
1284 : 16389 : CtxCaps(self) = 1;
1285 : 16389 : self->tstate = NULL;
1286 : :
1287 : 16389 : return (PyObject *)self;
1288 : : }
1289 : :
1290 : : static void
1291 : 16239 : context_dealloc(PyDecContextObject *self)
1292 : : {
1293 : : #ifndef WITH_DECIMAL_CONTEXTVAR
1294 : : if (self == cached_context) {
1295 : : cached_context = NULL;
1296 : : }
1297 : : #endif
1298 : :
1299 : 16239 : Py_XDECREF(self->traps);
1300 : 16239 : Py_XDECREF(self->flags);
1301 : 16239 : Py_TYPE(self)->tp_free(self);
1302 : 16239 : }
1303 : :
1304 : : static int
1305 : 16389 : context_init(PyObject *self, PyObject *args, PyObject *kwds)
1306 : : {
1307 : : static char *kwlist[] = {
1308 : : "prec", "rounding", "Emin", "Emax", "capitals", "clamp",
1309 : : "flags", "traps", NULL
1310 : : };
1311 : 16389 : PyObject *prec = Py_None;
1312 : 16389 : PyObject *rounding = Py_None;
1313 : 16389 : PyObject *emin = Py_None;
1314 : 16389 : PyObject *emax = Py_None;
1315 : 16389 : PyObject *capitals = Py_None;
1316 : 16389 : PyObject *clamp = Py_None;
1317 : 16389 : PyObject *status = Py_None;
1318 : 16389 : PyObject *traps = Py_None;
1319 : :
1320 : : assert(PyTuple_Check(args));
1321 : :
1322 [ - + ]: 16389 : if (!PyArg_ParseTupleAndKeywords(
1323 : : args, kwds,
1324 : : "|OOOOOOOO", kwlist,
1325 : : &prec, &rounding, &emin, &emax, &capitals, &clamp, &status, &traps
1326 : : )) {
1327 : 0 : return -1;
1328 : : }
1329 : :
1330 : 16389 : return context_setattrs(
1331 : : self, prec, rounding,
1332 : : emin, emax, capitals,
1333 : : clamp, status, traps
1334 : : );
1335 : : }
1336 : :
1337 : : static PyObject *
1338 : 2 : context_repr(PyDecContextObject *self)
1339 : : {
1340 : : mpd_context_t *ctx;
1341 : : char flags[MPD_MAX_SIGNAL_LIST];
1342 : : char traps[MPD_MAX_SIGNAL_LIST];
1343 : : int n, mem;
1344 : :
1345 : : assert(PyDecContext_Check(self));
1346 : 2 : ctx = CTX(self);
1347 : :
1348 : 2 : mem = MPD_MAX_SIGNAL_LIST;
1349 : 2 : n = mpd_lsnprint_signals(flags, mem, ctx->status, dec_signal_string);
1350 [ + - - + ]: 2 : if (n < 0 || n >= mem) {
1351 : 0 : INTERNAL_ERROR_PTR("context_repr");
1352 : : }
1353 : :
1354 : 2 : n = mpd_lsnprint_signals(traps, mem, ctx->traps, dec_signal_string);
1355 [ + - - + ]: 2 : if (n < 0 || n >= mem) {
1356 : 0 : INTERNAL_ERROR_PTR("context_repr");
1357 : : }
1358 : :
1359 : 2 : return PyUnicode_FromFormat(
1360 : : "Context(prec=%zd, rounding=%s, Emin=%zd, Emax=%zd, "
1361 : : "capitals=%d, clamp=%d, flags=%s, traps=%s)",
1362 : 2 : ctx->prec, mpd_round_string[ctx->round], ctx->emin, ctx->emax,
1363 : : self->capitals, ctx->clamp, flags, traps);
1364 : : }
1365 : :
1366 : : static void
1367 : 50 : init_basic_context(PyObject *v)
1368 : : {
1369 : 50 : mpd_context_t ctx = dflt_ctx;
1370 : :
1371 : 50 : ctx.prec = 9;
1372 : 50 : ctx.traps |= (MPD_Underflow|MPD_Clamped);
1373 : 50 : ctx.round = MPD_ROUND_HALF_UP;
1374 : :
1375 : 50 : *CTX(v) = ctx;
1376 : 50 : CtxCaps(v) = 1;
1377 : 50 : }
1378 : :
1379 : : static void
1380 : 50 : init_extended_context(PyObject *v)
1381 : : {
1382 : 50 : mpd_context_t ctx = dflt_ctx;
1383 : :
1384 : 50 : ctx.prec = 9;
1385 : 50 : ctx.traps = 0;
1386 : :
1387 : 50 : *CTX(v) = ctx;
1388 : 50 : CtxCaps(v) = 1;
1389 : 50 : }
1390 : :
1391 : : #ifdef EXTRA_FUNCTIONALITY
1392 : : /* Factory function for creating IEEE interchange format contexts */
1393 : : static PyObject *
1394 : : ieee_context(PyObject *dummy UNUSED, PyObject *v)
1395 : : {
1396 : : PyObject *context;
1397 : : mpd_ssize_t bits;
1398 : : mpd_context_t ctx;
1399 : :
1400 : : bits = PyLong_AsSsize_t(v);
1401 : : if (bits == -1 && PyErr_Occurred()) {
1402 : : return NULL;
1403 : : }
1404 : : if (bits <= 0 || bits > INT_MAX) {
1405 : : goto error;
1406 : : }
1407 : : if (mpd_ieee_context(&ctx, (int)bits) < 0) {
1408 : : goto error;
1409 : : }
1410 : :
1411 : : context = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
1412 : : if (context == NULL) {
1413 : : return NULL;
1414 : : }
1415 : : *CTX(context) = ctx;
1416 : :
1417 : : return context;
1418 : :
1419 : : error:
1420 : : PyErr_Format(PyExc_ValueError,
1421 : : "argument must be a multiple of 32, with a maximum of %d",
1422 : : MPD_IEEE_CONTEXT_MAX_BITS);
1423 : :
1424 : : return NULL;
1425 : : }
1426 : : #endif
1427 : :
1428 : : static PyObject *
1429 : 196 : context_copy(PyObject *self, PyObject *args UNUSED)
1430 : : {
1431 : : PyObject *copy;
1432 : :
1433 : 196 : copy = PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL);
1434 [ - + ]: 196 : if (copy == NULL) {
1435 : 0 : return NULL;
1436 : : }
1437 : :
1438 : 196 : *CTX(copy) = *CTX(self);
1439 : 196 : CTX(copy)->newtrap = 0;
1440 : 196 : CtxCaps(copy) = CtxCaps(self);
1441 : :
1442 : 196 : return copy;
1443 : : }
1444 : :
1445 : : static PyObject *
1446 : 7782 : context_reduce(PyObject *self, PyObject *args UNUSED)
1447 : : {
1448 : : PyObject *flags;
1449 : : PyObject *traps;
1450 : : PyObject *ret;
1451 : : mpd_context_t *ctx;
1452 : :
1453 : 7782 : ctx = CTX(self);
1454 : :
1455 : 7782 : flags = signals_as_list(ctx->status);
1456 [ - + ]: 7782 : if (flags == NULL) {
1457 : 0 : return NULL;
1458 : : }
1459 : 7782 : traps = signals_as_list(ctx->traps);
1460 [ - + ]: 7782 : if (traps == NULL) {
1461 : 0 : Py_DECREF(flags);
1462 : 0 : return NULL;
1463 : : }
1464 : :
1465 : 7782 : ret = Py_BuildValue(
1466 : : "O(nsnniiOO)",
1467 : : Py_TYPE(self),
1468 : 7782 : ctx->prec, mpd_round_string[ctx->round], ctx->emin, ctx->emax,
1469 : : CtxCaps(self), ctx->clamp, flags, traps
1470 : : );
1471 : :
1472 : 7782 : Py_DECREF(flags);
1473 : 7782 : Py_DECREF(traps);
1474 : 7782 : return ret;
1475 : : }
1476 : :
1477 : :
1478 : : static PyGetSetDef context_getsets [] =
1479 : : {
1480 : : { "prec", (getter)context_getprec, (setter)context_setprec, NULL, NULL},
1481 : : { "Emax", (getter)context_getemax, (setter)context_setemax, NULL, NULL},
1482 : : { "Emin", (getter)context_getemin, (setter)context_setemin, NULL, NULL},
1483 : : { "rounding", (getter)context_getround, (setter)context_setround, NULL, NULL},
1484 : : { "capitals", (getter)context_getcapitals, (setter)context_setcapitals, NULL, NULL},
1485 : : { "clamp", (getter)context_getclamp, (setter)context_setclamp, NULL, NULL},
1486 : : #ifdef EXTRA_FUNCTIONALITY
1487 : : { "_allcr", (getter)context_getallcr, (setter)context_setallcr, NULL, NULL},
1488 : : { "_traps", (getter)context_gettraps, (setter)context_settraps, NULL, NULL},
1489 : : { "_flags", (getter)context_getstatus, (setter)context_setstatus, NULL, NULL},
1490 : : #endif
1491 : : {NULL}
1492 : : };
1493 : :
1494 : :
1495 : : #define CONTEXT_CHECK(obj) \
1496 : : if (!PyDecContext_Check(obj)) { \
1497 : : PyErr_SetString(PyExc_TypeError, \
1498 : : "argument must be a context"); \
1499 : : return NULL; \
1500 : : }
1501 : :
1502 : : #define CONTEXT_CHECK_VA(obj) \
1503 : : if (obj == Py_None) { \
1504 : : CURRENT_CONTEXT(obj); \
1505 : : } \
1506 : : else if (!PyDecContext_Check(obj)) { \
1507 : : PyErr_SetString(PyExc_TypeError, \
1508 : : "optional argument must be a context"); \
1509 : : return NULL; \
1510 : : }
1511 : :
1512 : :
1513 : : /******************************************************************************/
1514 : : /* Global, thread local and temporary contexts */
1515 : : /******************************************************************************/
1516 : :
1517 : : /*
1518 : : * Thread local storage currently has a speed penalty of about 4%.
1519 : : * All functions that map Python's arithmetic operators to mpdecimal
1520 : : * functions have to look up the current context for each and every
1521 : : * operation.
1522 : : */
1523 : :
1524 : : #ifndef WITH_DECIMAL_CONTEXTVAR
1525 : : /* Get the context from the thread state dictionary. */
1526 : : static PyObject *
1527 : : current_context_from_dict(void)
1528 : : {
1529 : : PyThreadState *tstate = _PyThreadState_GET();
1530 : : #ifdef Py_DEBUG
1531 : : // The caller must hold the GIL
1532 : : _Py_EnsureTstateNotNULL(tstate);
1533 : : #endif
1534 : :
1535 : : PyObject *dict = _PyThreadState_GetDict(tstate);
1536 : : if (dict == NULL) {
1537 : : PyErr_SetString(PyExc_RuntimeError,
1538 : : "cannot get thread state");
1539 : : return NULL;
1540 : : }
1541 : :
1542 : : PyObject *tl_context = PyDict_GetItemWithError(dict, tls_context_key);
1543 : : if (tl_context != NULL) {
1544 : : /* We already have a thread local context. */
1545 : : CONTEXT_CHECK(tl_context);
1546 : : }
1547 : : else {
1548 : : if (PyErr_Occurred()) {
1549 : : return NULL;
1550 : : }
1551 : :
1552 : : /* Set up a new thread local context. */
1553 : : tl_context = context_copy(default_context_template, NULL);
1554 : : if (tl_context == NULL) {
1555 : : return NULL;
1556 : : }
1557 : : CTX(tl_context)->status = 0;
1558 : :
1559 : : if (PyDict_SetItem(dict, tls_context_key, tl_context) < 0) {
1560 : : Py_DECREF(tl_context);
1561 : : return NULL;
1562 : : }
1563 : : Py_DECREF(tl_context);
1564 : : }
1565 : :
1566 : : /* Cache the context of the current thread, assuming that it
1567 : : * will be accessed several times before a thread switch. */
1568 : : cached_context = (PyDecContextObject *)tl_context;
1569 : : cached_context->tstate = tstate;
1570 : :
1571 : : /* Borrowed reference with refcount==1 */
1572 : : return tl_context;
1573 : : }
1574 : :
1575 : : /* Return borrowed reference to thread local context. */
1576 : : static PyObject *
1577 : : current_context(void)
1578 : : {
1579 : : PyThreadState *tstate = _PyThreadState_GET();
1580 : : if (cached_context && cached_context->tstate == tstate) {
1581 : : return (PyObject *)cached_context;
1582 : : }
1583 : :
1584 : : return current_context_from_dict();
1585 : : }
1586 : :
1587 : : /* ctxobj := borrowed reference to the current context */
1588 : : #define CURRENT_CONTEXT(ctxobj) \
1589 : : ctxobj = current_context(); \
1590 : : if (ctxobj == NULL) { \
1591 : : return NULL; \
1592 : : }
1593 : :
1594 : : /* Return a new reference to the current context */
1595 : : static PyObject *
1596 : : PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
1597 : : {
1598 : : PyObject *context;
1599 : :
1600 : : context = current_context();
1601 : : if (context == NULL) {
1602 : : return NULL;
1603 : : }
1604 : :
1605 : : Py_INCREF(context);
1606 : : return context;
1607 : : }
1608 : :
1609 : : /* Set the thread local context to a new context, decrement old reference */
1610 : : static PyObject *
1611 : : PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
1612 : : {
1613 : : PyObject *dict;
1614 : :
1615 : : CONTEXT_CHECK(v);
1616 : :
1617 : : dict = PyThreadState_GetDict();
1618 : : if (dict == NULL) {
1619 : : PyErr_SetString(PyExc_RuntimeError,
1620 : : "cannot get thread state");
1621 : : return NULL;
1622 : : }
1623 : :
1624 : : /* If the new context is one of the templates, make a copy.
1625 : : * This is the current behavior of decimal.py. */
1626 : : if (v == default_context_template ||
1627 : : v == basic_context_template ||
1628 : : v == extended_context_template) {
1629 : : v = context_copy(v, NULL);
1630 : : if (v == NULL) {
1631 : : return NULL;
1632 : : }
1633 : : CTX(v)->status = 0;
1634 : : }
1635 : : else {
1636 : : Py_INCREF(v);
1637 : : }
1638 : :
1639 : : cached_context = NULL;
1640 : : if (PyDict_SetItem(dict, tls_context_key, v) < 0) {
1641 : : Py_DECREF(v);
1642 : : return NULL;
1643 : : }
1644 : :
1645 : : Py_DECREF(v);
1646 : : Py_RETURN_NONE;
1647 : : }
1648 : : #else
1649 : : static PyObject *
1650 : 24 : init_current_context(void)
1651 : : {
1652 : 24 : PyObject *tl_context = context_copy(default_context_template, NULL);
1653 [ - + ]: 24 : if (tl_context == NULL) {
1654 : 0 : return NULL;
1655 : : }
1656 : 24 : CTX(tl_context)->status = 0;
1657 : :
1658 : 24 : PyObject *tok = PyContextVar_Set(current_context_var, tl_context);
1659 [ - + ]: 24 : if (tok == NULL) {
1660 : 0 : Py_DECREF(tl_context);
1661 : 0 : return NULL;
1662 : : }
1663 : 24 : Py_DECREF(tok);
1664 : :
1665 : 24 : return tl_context;
1666 : : }
1667 : :
1668 : : static inline PyObject *
1669 : 238210 : current_context(void)
1670 : : {
1671 : : PyObject *tl_context;
1672 [ - + ]: 238210 : if (PyContextVar_Get(current_context_var, NULL, &tl_context) < 0) {
1673 : 0 : return NULL;
1674 : : }
1675 : :
1676 [ + + ]: 238210 : if (tl_context != NULL) {
1677 : 238186 : return tl_context;
1678 : : }
1679 : :
1680 : 24 : return init_current_context();
1681 : : }
1682 : :
1683 : : /* ctxobj := borrowed reference to the current context */
1684 : : #define CURRENT_CONTEXT(ctxobj) \
1685 : : ctxobj = current_context(); \
1686 : : if (ctxobj == NULL) { \
1687 : : return NULL; \
1688 : : } \
1689 : : Py_DECREF(ctxobj);
1690 : :
1691 : : /* Return a new reference to the current context */
1692 : : static PyObject *
1693 : 30 : PyDec_GetCurrentContext(PyObject *self UNUSED, PyObject *args UNUSED)
1694 : : {
1695 : 30 : return current_context();
1696 : : }
1697 : :
1698 : : /* Set the thread local context to a new context, decrement old reference */
1699 : : static PyObject *
1700 : 311 : PyDec_SetCurrentContext(PyObject *self UNUSED, PyObject *v)
1701 : : {
1702 [ + + ]: 311 : CONTEXT_CHECK(v);
1703 : :
1704 : : /* If the new context is one of the templates, make a copy.
1705 : : * This is the current behavior of decimal.py. */
1706 [ + + ]: 310 : if (v == default_context_template ||
1707 [ + + ]: 309 : v == basic_context_template ||
1708 [ + + ]: 308 : v == extended_context_template) {
1709 : 3 : v = context_copy(v, NULL);
1710 [ - + ]: 3 : if (v == NULL) {
1711 : 0 : return NULL;
1712 : : }
1713 : 3 : CTX(v)->status = 0;
1714 : : }
1715 : : else {
1716 : 307 : Py_INCREF(v);
1717 : : }
1718 : :
1719 : 310 : PyObject *tok = PyContextVar_Set(current_context_var, v);
1720 : 310 : Py_DECREF(v);
1721 [ - + ]: 310 : if (tok == NULL) {
1722 : 0 : return NULL;
1723 : : }
1724 : 310 : Py_DECREF(tok);
1725 : :
1726 : 310 : Py_RETURN_NONE;
1727 : : }
1728 : : #endif
1729 : :
1730 : : /* Context manager object for the 'with' statement. The manager
1731 : : * owns one reference to the global (outer) context and one
1732 : : * to the local (inner) context. */
1733 : : static PyObject *
1734 : 162 : ctxmanager_new(PyTypeObject *type UNUSED, PyObject *args, PyObject *kwds)
1735 : : {
1736 : : static char *kwlist[] = {
1737 : : "ctx", "prec", "rounding",
1738 : : "Emin", "Emax", "capitals",
1739 : : "clamp", "flags", "traps",
1740 : : NULL
1741 : : };
1742 : : PyDecContextManagerObject *self;
1743 : 162 : PyObject *local = Py_None;
1744 : : PyObject *global;
1745 : :
1746 : 162 : PyObject *prec = Py_None;
1747 : 162 : PyObject *rounding = Py_None;
1748 : 162 : PyObject *Emin = Py_None;
1749 : 162 : PyObject *Emax = Py_None;
1750 : 162 : PyObject *capitals = Py_None;
1751 : 162 : PyObject *clamp = Py_None;
1752 : 162 : PyObject *flags = Py_None;
1753 : 162 : PyObject *traps = Py_None;
1754 : :
1755 [ - + ]: 162 : CURRENT_CONTEXT(global);
1756 [ + + ]: 162 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOOOOO", kwlist, &local,
1757 : : &prec, &rounding, &Emin, &Emax, &capitals, &clamp, &flags, &traps)) {
1758 : 2 : return NULL;
1759 : : }
1760 [ + + ]: 160 : if (local == Py_None) {
1761 : 104 : local = global;
1762 : : }
1763 [ + + ]: 56 : else if (!PyDecContext_Check(local)) {
1764 : 1 : PyErr_SetString(PyExc_TypeError,
1765 : : "optional argument must be a context");
1766 : 1 : return NULL;
1767 : : }
1768 : :
1769 : 159 : self = PyObject_New(PyDecContextManagerObject,
1770 : : &PyDecContextManager_Type);
1771 [ - + ]: 159 : if (self == NULL) {
1772 : 0 : return NULL;
1773 : : }
1774 : :
1775 : 159 : self->local = context_copy(local, NULL);
1776 [ - + ]: 159 : if (self->local == NULL) {
1777 : 0 : self->global = NULL;
1778 : 0 : Py_DECREF(self);
1779 : 0 : return NULL;
1780 : : }
1781 : 159 : self->global = global;
1782 : 159 : Py_INCREF(self->global);
1783 : :
1784 : 159 : int ret = context_setattrs(
1785 : : self->local, prec, rounding,
1786 : : Emin, Emax, capitals,
1787 : : clamp, flags, traps
1788 : : );
1789 : :
1790 [ + + ]: 159 : if (ret < 0) {
1791 : 10 : Py_DECREF(self);
1792 : 10 : return NULL;
1793 : : }
1794 : :
1795 : 149 : return (PyObject *)self;
1796 : : }
1797 : :
1798 : : static void
1799 : 159 : ctxmanager_dealloc(PyDecContextManagerObject *self)
1800 : : {
1801 : 159 : Py_XDECREF(self->local);
1802 : 159 : Py_XDECREF(self->global);
1803 : 159 : PyObject_Free(self);
1804 : 159 : }
1805 : :
1806 : : static PyObject *
1807 : 149 : ctxmanager_set_local(PyDecContextManagerObject *self, PyObject *args UNUSED)
1808 : : {
1809 : : PyObject *ret;
1810 : :
1811 : 149 : ret = PyDec_SetCurrentContext(NULL, self->local);
1812 [ - + ]: 149 : if (ret == NULL) {
1813 : 0 : return NULL;
1814 : : }
1815 : 149 : Py_DECREF(ret);
1816 : :
1817 : 149 : Py_INCREF(self->local);
1818 : 149 : return self->local;
1819 : : }
1820 : :
1821 : : static PyObject *
1822 : 149 : ctxmanager_restore_global(PyDecContextManagerObject *self,
1823 : : PyObject *args UNUSED)
1824 : : {
1825 : : PyObject *ret;
1826 : :
1827 : 149 : ret = PyDec_SetCurrentContext(NULL, self->global);
1828 [ - + ]: 149 : if (ret == NULL) {
1829 : 0 : return NULL;
1830 : : }
1831 : 149 : Py_DECREF(ret);
1832 : :
1833 : 149 : Py_RETURN_NONE;
1834 : : }
1835 : :
1836 : :
1837 : : static PyMethodDef ctxmanager_methods[] = {
1838 : : {"__enter__", (PyCFunction)ctxmanager_set_local, METH_NOARGS, NULL},
1839 : : {"__exit__", (PyCFunction)ctxmanager_restore_global, METH_VARARGS, NULL},
1840 : : {NULL, NULL}
1841 : : };
1842 : :
1843 : : static PyTypeObject PyDecContextManager_Type =
1844 : : {
1845 : : PyVarObject_HEAD_INIT(NULL, 0)
1846 : : "decimal.ContextManager", /* tp_name */
1847 : : sizeof(PyDecContextManagerObject), /* tp_basicsize */
1848 : : 0, /* tp_itemsize */
1849 : : (destructor) ctxmanager_dealloc, /* tp_dealloc */
1850 : : 0, /* tp_vectorcall_offset */
1851 : : (getattrfunc) 0, /* tp_getattr */
1852 : : (setattrfunc) 0, /* tp_setattr */
1853 : : 0, /* tp_as_async */
1854 : : (reprfunc) 0, /* tp_repr */
1855 : : 0, /* tp_as_number */
1856 : : 0, /* tp_as_sequence */
1857 : : 0, /* tp_as_mapping */
1858 : : 0, /* tp_hash */
1859 : : 0, /* tp_call */
1860 : : 0, /* tp_str */
1861 : : (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */
1862 : : (setattrofunc) 0, /* tp_setattro */
1863 : : (PyBufferProcs *) 0, /* tp_as_buffer */
1864 : : Py_TPFLAGS_DEFAULT, /* tp_flags */
1865 : : 0, /* tp_doc */
1866 : : 0, /* tp_traverse */
1867 : : 0, /* tp_clear */
1868 : : 0, /* tp_richcompare */
1869 : : 0, /* tp_weaklistoffset */
1870 : : 0, /* tp_iter */
1871 : : 0, /* tp_iternext */
1872 : : ctxmanager_methods, /* tp_methods */
1873 : : };
1874 : :
1875 : :
1876 : : /******************************************************************************/
1877 : : /* New Decimal Object */
1878 : : /******************************************************************************/
1879 : :
1880 : : static PyObject *
1881 : 331493 : PyDecType_New(PyTypeObject *type)
1882 : : {
1883 : : PyDecObject *dec;
1884 : :
1885 [ + + ]: 331493 : if (type == &PyDec_Type) {
1886 : 331269 : dec = PyObject_New(PyDecObject, &PyDec_Type);
1887 : : }
1888 : : else {
1889 : 224 : dec = (PyDecObject *)type->tp_alloc(type, 0);
1890 : : }
1891 [ - + ]: 331493 : if (dec == NULL) {
1892 : 0 : return NULL;
1893 : : }
1894 : :
1895 : 331493 : dec->hash = -1;
1896 : :
1897 : 331493 : MPD(dec)->flags = MPD_STATIC|MPD_STATIC_DATA;
1898 : 331493 : MPD(dec)->exp = 0;
1899 : 331493 : MPD(dec)->digits = 0;
1900 : 331493 : MPD(dec)->len = 0;
1901 : 331493 : MPD(dec)->alloc = _Py_DEC_MINALLOC;
1902 : 331493 : MPD(dec)->data = dec->data;
1903 : :
1904 : 331493 : return (PyObject *)dec;
1905 : : }
1906 : : #define dec_alloc() PyDecType_New(&PyDec_Type)
1907 : :
1908 : : static void
1909 : 331493 : dec_dealloc(PyObject *dec)
1910 : : {
1911 : 331493 : mpd_del(MPD(dec));
1912 : 331493 : Py_TYPE(dec)->tp_free(dec);
1913 : 331493 : }
1914 : :
1915 : :
1916 : : /******************************************************************************/
1917 : : /* Conversions to Decimal */
1918 : : /******************************************************************************/
1919 : :
1920 : : Py_LOCAL_INLINE(int)
1921 : 263251 : is_space(int kind, const void *data, Py_ssize_t pos)
1922 : : {
1923 : 263251 : Py_UCS4 ch = PyUnicode_READ(kind, data, pos);
1924 : 263251 : return Py_UNICODE_ISSPACE(ch);
1925 : : }
1926 : :
1927 : : /* Return the ASCII representation of a numeric Unicode string. The numeric
1928 : : string may contain ascii characters in the range [1, 127], any Unicode
1929 : : space and any unicode digit. If strip_ws is true, leading and trailing
1930 : : whitespace is stripped. If ignore_underscores is true, underscores are
1931 : : ignored.
1932 : :
1933 : : Return NULL if malloc fails and an empty string if invalid characters
1934 : : are found. */
1935 : : static char *
1936 : 135567 : numeric_as_ascii(PyObject *u, int strip_ws, int ignore_underscores)
1937 : : {
1938 : : int kind;
1939 : : const void *data;
1940 : : Py_UCS4 ch;
1941 : : char *res, *cp;
1942 : : Py_ssize_t j, len;
1943 : : int d;
1944 : :
1945 [ - + ]: 135567 : if (PyUnicode_READY(u) == -1) {
1946 : 0 : return NULL;
1947 : : }
1948 : :
1949 : 135567 : kind = PyUnicode_KIND(u);
1950 : 135567 : data = PyUnicode_DATA(u);
1951 : 135567 : len = PyUnicode_GET_LENGTH(u);
1952 : :
1953 : 135567 : cp = res = PyMem_Malloc(len+1);
1954 [ - + ]: 135567 : if (res == NULL) {
1955 : : PyErr_NoMemory();
1956 : 0 : return NULL;
1957 : : }
1958 : :
1959 : 135567 : j = 0;
1960 [ + + ]: 135567 : if (strip_ws) {
1961 [ + + + + ]: 131630 : while (len > 0 && is_space(kind, data, len-1)) {
1962 : 20 : len--;
1963 : : }
1964 [ + + + + ]: 131627 : while (j < len && is_space(kind, data, j)) {
1965 : 17 : j++;
1966 : : }
1967 : : }
1968 : :
1969 [ + + ]: 1195412 : for (; j < len; j++) {
1970 : 1059847 : ch = PyUnicode_READ(kind, data, j);
1971 [ + + + + ]: 1059847 : if (ignore_underscores && ch == '_') {
1972 : 7 : continue;
1973 : : }
1974 [ + + + + ]: 1059840 : if (0 < ch && ch <= 127) {
1975 : 1059824 : *cp++ = ch;
1976 : 1059824 : continue;
1977 : : }
1978 [ + + ]: 16 : if (Py_UNICODE_ISSPACE(ch)) {
1979 : 3 : *cp++ = ' ';
1980 : 3 : continue;
1981 : : }
1982 : 13 : d = Py_UNICODE_TODECIMAL(ch);
1983 [ + + ]: 13 : if (d < 0) {
1984 : : /* empty string triggers ConversionSyntax */
1985 : 2 : *res = '\0';
1986 : 2 : return res;
1987 : : }
1988 : 11 : *cp++ = '0' + d;
1989 : : }
1990 : 135565 : *cp = '\0';
1991 : 135565 : return res;
1992 : : }
1993 : :
1994 : : /* Return a new PyDecObject or a subtype from a C string. Use the context
1995 : : during conversion. */
1996 : : static PyObject *
1997 : 3962 : PyDecType_FromCString(PyTypeObject *type, const char *s,
1998 : : PyObject *context)
1999 : : {
2000 : : PyObject *dec;
2001 : 3962 : uint32_t status = 0;
2002 : :
2003 : 3962 : dec = PyDecType_New(type);
2004 [ - + ]: 3962 : if (dec == NULL) {
2005 : 0 : return NULL;
2006 : : }
2007 : :
2008 : 3962 : mpd_qset_string(MPD(dec), s, CTX(context), &status);
2009 [ + + ]: 3962 : if (dec_addstatus(context, status)) {
2010 : 7 : Py_DECREF(dec);
2011 : 7 : return NULL;
2012 : : }
2013 : 3955 : return dec;
2014 : : }
2015 : :
2016 : : /* Return a new PyDecObject or a subtype from a C string. Attempt exact
2017 : : conversion. If the operand cannot be converted exactly, set
2018 : : InvalidOperation. */
2019 : : static PyObject *
2020 : 131640 : PyDecType_FromCStringExact(PyTypeObject *type, const char *s,
2021 : : PyObject *context)
2022 : : {
2023 : : PyObject *dec;
2024 : 131640 : uint32_t status = 0;
2025 : : mpd_context_t maxctx;
2026 : :
2027 : 131640 : dec = PyDecType_New(type);
2028 [ - + ]: 131640 : if (dec == NULL) {
2029 : 0 : return NULL;
2030 : : }
2031 : :
2032 : 131640 : mpd_maxcontext(&maxctx);
2033 : :
2034 : 131640 : mpd_qset_string(MPD(dec), s, &maxctx, &status);
2035 [ + + ]: 131640 : if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
2036 : : /* we want exact results */
2037 : 9 : mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
2038 : : }
2039 : 131640 : status &= MPD_Errors;
2040 [ + + ]: 131640 : if (dec_addstatus(context, status)) {
2041 : 17 : Py_DECREF(dec);
2042 : 17 : return NULL;
2043 : : }
2044 : :
2045 : 131623 : return dec;
2046 : : }
2047 : :
2048 : : /* Return a new PyDecObject or a subtype from a PyUnicodeObject. */
2049 : : static PyObject *
2050 : 3957 : PyDecType_FromUnicode(PyTypeObject *type, PyObject *u,
2051 : : PyObject *context)
2052 : : {
2053 : : PyObject *dec;
2054 : : char *s;
2055 : :
2056 : 3957 : s = numeric_as_ascii(u, 0, 0);
2057 [ - + ]: 3957 : if (s == NULL) {
2058 : 0 : return NULL;
2059 : : }
2060 : :
2061 : 3957 : dec = PyDecType_FromCString(type, s, context);
2062 : 3957 : PyMem_Free(s);
2063 : 3957 : return dec;
2064 : : }
2065 : :
2066 : : /* Return a new PyDecObject or a subtype from a PyUnicodeObject. Attempt exact
2067 : : * conversion. If the conversion is not exact, fail with InvalidOperation.
2068 : : * Allow leading and trailing whitespace in the input operand. */
2069 : : static PyObject *
2070 : 131610 : PyDecType_FromUnicodeExactWS(PyTypeObject *type, PyObject *u,
2071 : : PyObject *context)
2072 : : {
2073 : : PyObject *dec;
2074 : : char *s;
2075 : :
2076 : 131610 : s = numeric_as_ascii(u, 1, 1);
2077 [ - + ]: 131610 : if (s == NULL) {
2078 : 0 : return NULL;
2079 : : }
2080 : :
2081 : 131610 : dec = PyDecType_FromCStringExact(type, s, context);
2082 : 131610 : PyMem_Free(s);
2083 : 131610 : return dec;
2084 : : }
2085 : :
2086 : : /* Set PyDecObject from triple without any error checking. */
2087 : : Py_LOCAL_INLINE(void)
2088 : 61584 : _dec_settriple(PyObject *dec, uint8_t sign, uint32_t v, mpd_ssize_t exp)
2089 : : {
2090 : :
2091 : : #ifdef CONFIG_64
2092 : 61584 : MPD(dec)->data[0] = v;
2093 : 61584 : MPD(dec)->len = 1;
2094 : : #else
2095 : : uint32_t q, r;
2096 : : q = v / MPD_RADIX;
2097 : : r = v - q * MPD_RADIX;
2098 : : MPD(dec)->data[1] = q;
2099 : : MPD(dec)->data[0] = r;
2100 : : MPD(dec)->len = q ? 2 : 1;
2101 : : #endif
2102 : 61584 : mpd_set_flags(MPD(dec), sign);
2103 : 61584 : MPD(dec)->exp = exp;
2104 : 61584 : mpd_setdigits(MPD(dec));
2105 : 61584 : }
2106 : :
2107 : : /* Return a new PyDecObject from an mpd_ssize_t. */
2108 : : static PyObject *
2109 : 1 : PyDecType_FromSsize(PyTypeObject *type, mpd_ssize_t v, PyObject *context)
2110 : : {
2111 : : PyObject *dec;
2112 : 1 : uint32_t status = 0;
2113 : :
2114 : 1 : dec = PyDecType_New(type);
2115 [ - + ]: 1 : if (dec == NULL) {
2116 : 0 : return NULL;
2117 : : }
2118 : :
2119 : 1 : mpd_qset_ssize(MPD(dec), v, CTX(context), &status);
2120 [ - + ]: 1 : if (dec_addstatus(context, status)) {
2121 : 0 : Py_DECREF(dec);
2122 : 0 : return NULL;
2123 : : }
2124 : 1 : return dec;
2125 : : }
2126 : :
2127 : : /* Return a new PyDecObject from an mpd_ssize_t. Conversion is exact. */
2128 : : static PyObject *
2129 : 3 : PyDecType_FromSsizeExact(PyTypeObject *type, mpd_ssize_t v, PyObject *context)
2130 : : {
2131 : : PyObject *dec;
2132 : 3 : uint32_t status = 0;
2133 : : mpd_context_t maxctx;
2134 : :
2135 : 3 : dec = PyDecType_New(type);
2136 [ - + ]: 3 : if (dec == NULL) {
2137 : 0 : return NULL;
2138 : : }
2139 : :
2140 : 3 : mpd_maxcontext(&maxctx);
2141 : :
2142 : 3 : mpd_qset_ssize(MPD(dec), v, &maxctx, &status);
2143 [ - + ]: 3 : if (dec_addstatus(context, status)) {
2144 : 0 : Py_DECREF(dec);
2145 : 0 : return NULL;
2146 : : }
2147 : 3 : return dec;
2148 : : }
2149 : :
2150 : : /* Convert from a PyLongObject. The context is not modified; flags set
2151 : : during conversion are accumulated in the status parameter. */
2152 : : static PyObject *
2153 : 76858 : dec_from_long(PyTypeObject *type, PyObject *v,
2154 : : const mpd_context_t *ctx, uint32_t *status)
2155 : : {
2156 : : PyObject *dec;
2157 : 76858 : PyLongObject *l = (PyLongObject *)v;
2158 : : Py_ssize_t ob_size;
2159 : : size_t len;
2160 : : uint8_t sign;
2161 : :
2162 : 76858 : dec = PyDecType_New(type);
2163 [ - + ]: 76858 : if (dec == NULL) {
2164 : 0 : return NULL;
2165 : : }
2166 : :
2167 : 76858 : ob_size = Py_SIZE(l);
2168 [ + + ]: 76858 : if (ob_size == 0) {
2169 : 1522 : _dec_settriple(dec, MPD_POS, 0, 0);
2170 : 1522 : return dec;
2171 : : }
2172 : :
2173 [ + + ]: 75336 : if (ob_size < 0) {
2174 : 11825 : len = -ob_size;
2175 : 11825 : sign = MPD_NEG;
2176 : : }
2177 : : else {
2178 : 63511 : len = ob_size;
2179 : 63511 : sign = MPD_POS;
2180 : : }
2181 : :
2182 [ + + ]: 75336 : if (len == 1) {
2183 : 60056 : _dec_settriple(dec, sign, *l->ob_digit, 0);
2184 : 60056 : mpd_qfinalize(MPD(dec), ctx, status);
2185 : 60056 : return dec;
2186 : : }
2187 : :
2188 : : #if PYLONG_BITS_IN_DIGIT == 30
2189 : 15280 : mpd_qimport_u32(MPD(dec), l->ob_digit, len, sign, PyLong_BASE,
2190 : : ctx, status);
2191 : : #elif PYLONG_BITS_IN_DIGIT == 15
2192 : : mpd_qimport_u16(MPD(dec), l->ob_digit, len, sign, PyLong_BASE,
2193 : : ctx, status);
2194 : : #else
2195 : : #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
2196 : : #endif
2197 : :
2198 : 15280 : return dec;
2199 : : }
2200 : :
2201 : : /* Return a new PyDecObject from a PyLongObject. Use the context for
2202 : : conversion. */
2203 : : static PyObject *
2204 : 12 : PyDecType_FromLong(PyTypeObject *type, PyObject *v, PyObject *context)
2205 : : {
2206 : : PyObject *dec;
2207 : 12 : uint32_t status = 0;
2208 : :
2209 [ - + ]: 12 : if (!PyLong_Check(v)) {
2210 : 0 : PyErr_SetString(PyExc_TypeError, "argument must be an integer");
2211 : 0 : return NULL;
2212 : : }
2213 : :
2214 : 12 : dec = dec_from_long(type, v, CTX(context), &status);
2215 [ - + ]: 12 : if (dec == NULL) {
2216 : 0 : return NULL;
2217 : : }
2218 : :
2219 [ + + ]: 12 : if (dec_addstatus(context, status)) {
2220 : 1 : Py_DECREF(dec);
2221 : 1 : return NULL;
2222 : : }
2223 : :
2224 : 11 : return dec;
2225 : : }
2226 : :
2227 : : /* Return a new PyDecObject from a PyLongObject. Use a maximum context
2228 : : for conversion. If the conversion is not exact, set InvalidOperation. */
2229 : : static PyObject *
2230 : 76846 : PyDecType_FromLongExact(PyTypeObject *type, PyObject *v,
2231 : : PyObject *context)
2232 : : {
2233 : : PyObject *dec;
2234 : 76846 : uint32_t status = 0;
2235 : : mpd_context_t maxctx;
2236 : :
2237 [ - + ]: 76846 : if (!PyLong_Check(v)) {
2238 : 0 : PyErr_SetString(PyExc_TypeError, "argument must be an integer");
2239 : 0 : return NULL;
2240 : : }
2241 : :
2242 : 76846 : mpd_maxcontext(&maxctx);
2243 : 76846 : dec = dec_from_long(type, v, &maxctx, &status);
2244 [ - + ]: 76846 : if (dec == NULL) {
2245 : 0 : return NULL;
2246 : : }
2247 : :
2248 [ - + ]: 76846 : if (status & (MPD_Inexact|MPD_Rounded|MPD_Clamped)) {
2249 : : /* we want exact results */
2250 : 0 : mpd_seterror(MPD(dec), MPD_Invalid_operation, &status);
2251 : : }
2252 : 76846 : status &= MPD_Errors;
2253 [ - + ]: 76846 : if (dec_addstatus(context, status)) {
2254 : 0 : Py_DECREF(dec);
2255 : 0 : return NULL;
2256 : : }
2257 : :
2258 : 76846 : return dec;
2259 : : }
2260 : :
2261 : : /* External C-API functions */
2262 : : static binaryfunc _py_long_multiply;
2263 : : static binaryfunc _py_long_floor_divide;
2264 : : static ternaryfunc _py_long_power;
2265 : : static unaryfunc _py_float_abs;
2266 : : static PyCFunction _py_long_bit_length;
2267 : : static PyCFunction _py_float_as_integer_ratio;
2268 : :
2269 : : /* Return a PyDecObject or a subtype from a PyFloatObject.
2270 : : Conversion is exact. */
2271 : : static PyObject *
2272 : 13382 : PyDecType_FromFloatExact(PyTypeObject *type, PyObject *v,
2273 : : PyObject *context)
2274 : : {
2275 : : PyObject *dec, *tmp;
2276 : : PyObject *n, *d, *n_d;
2277 : : mpd_ssize_t k;
2278 : : double x;
2279 : : int sign;
2280 : : mpd_t *d1, *d2;
2281 : 13382 : uint32_t status = 0;
2282 : : mpd_context_t maxctx;
2283 : :
2284 : :
2285 : : assert(PyType_IsSubtype(type, &PyDec_Type));
2286 : :
2287 [ + + ]: 13382 : if (PyLong_Check(v)) {
2288 : 3 : return PyDecType_FromLongExact(type, v, context);
2289 : : }
2290 [ + + ]: 13379 : if (!PyFloat_Check(v)) {
2291 : 1 : PyErr_SetString(PyExc_TypeError,
2292 : : "argument must be int or float");
2293 : 1 : return NULL;
2294 : : }
2295 : :
2296 : 13378 : x = PyFloat_AsDouble(v);
2297 [ + + - + ]: 13378 : if (x == -1.0 && PyErr_Occurred()) {
2298 : 0 : return NULL;
2299 : : }
2300 : 13378 : sign = (copysign(1.0, x) == 1.0) ? 0 : 1;
2301 : :
2302 [ + + + + ]: 13378 : if (Py_IS_NAN(x) || Py_IS_INFINITY(x)) {
2303 : 53 : dec = PyDecType_New(type);
2304 [ - + ]: 53 : if (dec == NULL) {
2305 : 0 : return NULL;
2306 : : }
2307 [ + + ]: 53 : if (Py_IS_NAN(x)) {
2308 : : /* decimal.py calls repr(float(+-nan)),
2309 : : * which always gives a positive result. */
2310 : 9 : mpd_setspecial(MPD(dec), MPD_POS, MPD_NAN);
2311 : : }
2312 : : else {
2313 : 44 : mpd_setspecial(MPD(dec), sign, MPD_INF);
2314 : : }
2315 : 53 : return dec;
2316 : : }
2317 : :
2318 : : /* absolute value of the float */
2319 : 13325 : tmp = _py_float_abs(v);
2320 [ - + ]: 13325 : if (tmp == NULL) {
2321 : 0 : return NULL;
2322 : : }
2323 : :
2324 : : /* float as integer ratio: numerator/denominator */
2325 : 13325 : n_d = _py_float_as_integer_ratio(tmp, NULL);
2326 : 13325 : Py_DECREF(tmp);
2327 [ - + ]: 13325 : if (n_d == NULL) {
2328 : 0 : return NULL;
2329 : : }
2330 : 13325 : n = PyTuple_GET_ITEM(n_d, 0);
2331 : 13325 : d = PyTuple_GET_ITEM(n_d, 1);
2332 : :
2333 : 13325 : tmp = _py_long_bit_length(d, NULL);
2334 [ - + ]: 13325 : if (tmp == NULL) {
2335 : 0 : Py_DECREF(n_d);
2336 : 0 : return NULL;
2337 : : }
2338 : 13325 : k = PyLong_AsSsize_t(tmp);
2339 : 13325 : Py_DECREF(tmp);
2340 [ - + - - ]: 13325 : if (k == -1 && PyErr_Occurred()) {
2341 : 0 : Py_DECREF(n_d);
2342 : 0 : return NULL;
2343 : : }
2344 : 13325 : k--;
2345 : :
2346 : 13325 : dec = PyDecType_FromLongExact(type, n, context);
2347 : 13325 : Py_DECREF(n_d);
2348 [ - + ]: 13325 : if (dec == NULL) {
2349 : 0 : return NULL;
2350 : : }
2351 : :
2352 : 13325 : d1 = mpd_qnew();
2353 [ - + ]: 13325 : if (d1 == NULL) {
2354 : 0 : Py_DECREF(dec);
2355 : : PyErr_NoMemory();
2356 : 0 : return NULL;
2357 : : }
2358 : 13325 : d2 = mpd_qnew();
2359 [ - + ]: 13325 : if (d2 == NULL) {
2360 : 0 : mpd_del(d1);
2361 : 0 : Py_DECREF(dec);
2362 : : PyErr_NoMemory();
2363 : 0 : return NULL;
2364 : : }
2365 : :
2366 : 13325 : mpd_maxcontext(&maxctx);
2367 : 13325 : mpd_qset_uint(d1, 5, &maxctx, &status);
2368 : 13325 : mpd_qset_ssize(d2, k, &maxctx, &status);
2369 : 13325 : mpd_qpow(d1, d1, d2, &maxctx, &status);
2370 [ - + ]: 13325 : if (dec_addstatus(context, status)) {
2371 : 0 : mpd_del(d1);
2372 : 0 : mpd_del(d2);
2373 : 0 : Py_DECREF(dec);
2374 : 0 : return NULL;
2375 : : }
2376 : :
2377 : : /* result = n * 5**k */
2378 : 13325 : mpd_qmul(MPD(dec), MPD(dec), d1, &maxctx, &status);
2379 : 13325 : mpd_del(d1);
2380 : 13325 : mpd_del(d2);
2381 [ - + ]: 13325 : if (dec_addstatus(context, status)) {
2382 : 0 : Py_DECREF(dec);
2383 : 0 : return NULL;
2384 : : }
2385 : : /* result = +- n * 5**k * 10**-k */
2386 : 13325 : mpd_set_sign(MPD(dec), sign);
2387 : 13325 : MPD(dec)->exp = -k;
2388 : :
2389 : 13325 : return dec;
2390 : : }
2391 : :
2392 : : static PyObject *
2393 : 218 : PyDecType_FromFloat(PyTypeObject *type, PyObject *v,
2394 : : PyObject *context)
2395 : : {
2396 : : PyObject *dec;
2397 : 218 : uint32_t status = 0;
2398 : :
2399 : 218 : dec = PyDecType_FromFloatExact(type, v, context);
2400 [ - + ]: 218 : if (dec == NULL) {
2401 : 0 : return NULL;
2402 : : }
2403 : :
2404 : 218 : mpd_qfinalize(MPD(dec), CTX(context), &status);
2405 [ + + ]: 218 : if (dec_addstatus(context, status)) {
2406 : 1 : Py_DECREF(dec);
2407 : 1 : return NULL;
2408 : : }
2409 : :
2410 : 217 : return dec;
2411 : : }
2412 : :
2413 : : /* Return a new PyDecObject or a subtype from a Decimal. */
2414 : : static PyObject *
2415 : 3025 : PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context)
2416 : : {
2417 : : PyObject *dec;
2418 : 3025 : uint32_t status = 0;
2419 : :
2420 [ + + + + ]: 3025 : if (type == &PyDec_Type && PyDec_CheckExact(v)) {
2421 : 2809 : Py_INCREF(v);
2422 : 2809 : return v;
2423 : : }
2424 : :
2425 : 216 : dec = PyDecType_New(type);
2426 [ - + ]: 216 : if (dec == NULL) {
2427 : 0 : return NULL;
2428 : : }
2429 : :
2430 : 216 : mpd_qcopy(MPD(dec), MPD(v), &status);
2431 [ - + ]: 216 : if (dec_addstatus(context, status)) {
2432 : 0 : Py_DECREF(dec);
2433 : 0 : return NULL;
2434 : : }
2435 : :
2436 : 216 : return dec;
2437 : : }
2438 : :
2439 : : static PyObject *
2440 : 94 : sequence_as_tuple(PyObject *v, PyObject *ex, const char *mesg)
2441 : : {
2442 [ + + ]: 94 : if (PyTuple_Check(v)) {
2443 : 85 : Py_INCREF(v);
2444 : 85 : return v;
2445 : : }
2446 [ + + ]: 9 : if (PyList_Check(v)) {
2447 : 7 : return PyList_AsTuple(v);
2448 : : }
2449 : :
2450 : 2 : PyErr_SetString(ex, mesg);
2451 : 2 : return NULL;
2452 : : }
2453 : :
2454 : : /* Return a new C string representation of a DecimalTuple. */
2455 : : static char *
2456 : 53 : dectuple_as_str(PyObject *dectuple)
2457 : : {
2458 : 53 : PyObject *digits = NULL, *tmp;
2459 : 53 : char *decstring = NULL;
2460 : : char sign_special[6];
2461 : : char *cp;
2462 : : long sign, l;
2463 : 53 : mpd_ssize_t exp = 0;
2464 : : Py_ssize_t i, mem, tsize;
2465 : 53 : int is_infinite = 0;
2466 : : int n;
2467 : :
2468 : : assert(PyTuple_Check(dectuple));
2469 : :
2470 [ + + ]: 53 : if (PyTuple_Size(dectuple) != 3) {
2471 : 2 : PyErr_SetString(PyExc_ValueError,
2472 : : "argument must be a sequence of length 3");
2473 : 2 : goto error;
2474 : : }
2475 : :
2476 : : /* sign */
2477 : 51 : tmp = PyTuple_GET_ITEM(dectuple, 0);
2478 [ + + ]: 51 : if (!PyLong_Check(tmp)) {
2479 : 2 : PyErr_SetString(PyExc_ValueError,
2480 : : "sign must be an integer with the value 0 or 1");
2481 : 2 : goto error;
2482 : : }
2483 : 49 : sign = PyLong_AsLong(tmp);
2484 [ - + - - ]: 49 : if (sign == -1 && PyErr_Occurred()) {
2485 : 0 : goto error;
2486 : : }
2487 [ + + + + ]: 49 : if (sign != 0 && sign != 1) {
2488 : 1 : PyErr_SetString(PyExc_ValueError,
2489 : : "sign must be an integer with the value 0 or 1");
2490 : 1 : goto error;
2491 : : }
2492 [ + + ]: 48 : sign_special[0] = sign ? '-' : '+';
2493 : 48 : sign_special[1] = '\0';
2494 : :
2495 : : /* exponent or encoding for a special number */
2496 : 48 : tmp = PyTuple_GET_ITEM(dectuple, 2);
2497 [ + + ]: 48 : if (PyUnicode_Check(tmp)) {
2498 : : /* special */
2499 [ + + ]: 12 : if (PyUnicode_CompareWithASCIIString(tmp, "F") == 0) {
2500 : 4 : strcat(sign_special, "Inf");
2501 : 4 : is_infinite = 1;
2502 : : }
2503 [ + + ]: 8 : else if (PyUnicode_CompareWithASCIIString(tmp, "n") == 0) {
2504 : 2 : strcat(sign_special, "NaN");
2505 : : }
2506 [ + + ]: 6 : else if (PyUnicode_CompareWithASCIIString(tmp, "N") == 0) {
2507 : 4 : strcat(sign_special, "sNaN");
2508 : : }
2509 : : else {
2510 : 2 : PyErr_SetString(PyExc_ValueError,
2511 : : "string argument in the third position "
2512 : : "must be 'F', 'n' or 'N'");
2513 : 2 : goto error;
2514 : : }
2515 : : }
2516 : : else {
2517 : : /* exponent */
2518 [ + + ]: 36 : if (!PyLong_Check(tmp)) {
2519 : 1 : PyErr_SetString(PyExc_ValueError,
2520 : : "exponent must be an integer");
2521 : 1 : goto error;
2522 : : }
2523 : 35 : exp = PyLong_AsSsize_t(tmp);
2524 [ + + + - ]: 35 : if (exp == -1 && PyErr_Occurred()) {
2525 : 4 : goto error;
2526 : : }
2527 : : }
2528 : :
2529 : : /* coefficient */
2530 : 41 : digits = sequence_as_tuple(PyTuple_GET_ITEM(dectuple, 1), PyExc_ValueError,
2531 : : "coefficient must be a tuple of digits");
2532 [ + + ]: 41 : if (digits == NULL) {
2533 : 2 : goto error;
2534 : : }
2535 : :
2536 : 39 : tsize = PyTuple_Size(digits);
2537 : : /* [sign][coeffdigits+1][E][-][expdigits+1]['\0'] */
2538 : 39 : mem = 1 + tsize + 3 + MPD_EXPDIGITS + 2;
2539 : 39 : cp = decstring = PyMem_Malloc(mem);
2540 [ - + ]: 39 : if (decstring == NULL) {
2541 : : PyErr_NoMemory();
2542 : 0 : goto error;
2543 : : }
2544 : :
2545 : 39 : n = snprintf(cp, mem, "%s", sign_special);
2546 [ + - - + ]: 39 : if (n < 0 || n >= mem) {
2547 : 0 : PyErr_SetString(PyExc_RuntimeError,
2548 : : "internal error in dec_sequence_as_str");
2549 : 0 : goto error;
2550 : : }
2551 : 39 : cp += n;
2552 : :
2553 [ + + + + ]: 39 : if (tsize == 0 && sign_special[1] == '\0') {
2554 : : /* empty tuple: zero coefficient, except for special numbers */
2555 : 5 : *cp++ = '0';
2556 : : }
2557 [ + + ]: 169 : for (i = 0; i < tsize; i++) {
2558 : 134 : tmp = PyTuple_GET_ITEM(digits, i);
2559 [ + + ]: 134 : if (!PyLong_Check(tmp)) {
2560 : 2 : PyErr_SetString(PyExc_ValueError,
2561 : : "coefficient must be a tuple of digits");
2562 : 2 : goto error;
2563 : : }
2564 : 132 : l = PyLong_AsLong(tmp);
2565 [ - + - - ]: 132 : if (l == -1 && PyErr_Occurred()) {
2566 : 0 : goto error;
2567 : : }
2568 [ + + + + ]: 132 : if (l < 0 || l > 9) {
2569 : 2 : PyErr_SetString(PyExc_ValueError,
2570 : : "coefficient must be a tuple of digits");
2571 : 2 : goto error;
2572 : : }
2573 [ + + ]: 130 : if (is_infinite) {
2574 : : /* accept but ignore any well-formed coefficient for compatibility
2575 : : with decimal.py */
2576 : 9 : continue;
2577 : : }
2578 : 121 : *cp++ = (char)l + '0';
2579 : : }
2580 : 35 : *cp = '\0';
2581 : :
2582 [ + + ]: 35 : if (sign_special[1] == '\0') {
2583 : : /* not a special number */
2584 : 25 : *cp++ = 'E';
2585 : 25 : n = snprintf(cp, MPD_EXPDIGITS+2, "%" PRI_mpd_ssize_t, exp);
2586 [ + - - + ]: 25 : if (n < 0 || n >= MPD_EXPDIGITS+2) {
2587 : 0 : PyErr_SetString(PyExc_RuntimeError,
2588 : : "internal error in dec_sequence_as_str");
2589 : 0 : goto error;
2590 : : }
2591 : : }
2592 : :
2593 : 35 : Py_XDECREF(digits);
2594 : 35 : return decstring;
2595 : :
2596 : :
2597 : 18 : error:
2598 : 18 : Py_XDECREF(digits);
2599 [ + + ]: 18 : if (decstring) PyMem_Free(decstring);
2600 : 18 : return NULL;
2601 : : }
2602 : :
2603 : : /* Currently accepts tuples and lists. */
2604 : : static PyObject *
2605 : 9 : PyDecType_FromSequence(PyTypeObject *type, PyObject *v,
2606 : : PyObject *context)
2607 : : {
2608 : : PyObject *dectuple;
2609 : : PyObject *dec;
2610 : : char *s;
2611 : :
2612 : 9 : dectuple = sequence_as_tuple(v, PyExc_TypeError,
2613 : : "argument must be a tuple or list");
2614 [ - + ]: 9 : if (dectuple == NULL) {
2615 : 0 : return NULL;
2616 : : }
2617 : :
2618 : 9 : s = dectuple_as_str(dectuple);
2619 : 9 : Py_DECREF(dectuple);
2620 [ + + ]: 9 : if (s == NULL) {
2621 : 4 : return NULL;
2622 : : }
2623 : :
2624 : 5 : dec = PyDecType_FromCString(type, s, context);
2625 : :
2626 : 5 : PyMem_Free(s);
2627 : 5 : return dec;
2628 : : }
2629 : :
2630 : : /* Currently accepts tuples and lists. */
2631 : : static PyObject *
2632 : 44 : PyDecType_FromSequenceExact(PyTypeObject *type, PyObject *v,
2633 : : PyObject *context)
2634 : : {
2635 : : PyObject *dectuple;
2636 : : PyObject *dec;
2637 : : char *s;
2638 : :
2639 : 44 : dectuple = sequence_as_tuple(v, PyExc_TypeError,
2640 : : "argument must be a tuple or list");
2641 [ - + ]: 44 : if (dectuple == NULL) {
2642 : 0 : return NULL;
2643 : : }
2644 : :
2645 : 44 : s = dectuple_as_str(dectuple);
2646 : 44 : Py_DECREF(dectuple);
2647 [ + + ]: 44 : if (s == NULL) {
2648 : 14 : return NULL;
2649 : : }
2650 : :
2651 : 30 : dec = PyDecType_FromCStringExact(type, s, context);
2652 : :
2653 : 30 : PyMem_Free(s);
2654 : 30 : return dec;
2655 : : }
2656 : :
2657 : : #define PyDec_FromCString(str, context) \
2658 : : PyDecType_FromCString(&PyDec_Type, str, context)
2659 : : #define PyDec_FromCStringExact(str, context) \
2660 : : PyDecType_FromCStringExact(&PyDec_Type, str, context)
2661 : :
2662 : : #define PyDec_FromUnicode(unicode, context) \
2663 : : PyDecType_FromUnicode(&PyDec_Type, unicode, context)
2664 : : #define PyDec_FromUnicodeExact(unicode, context) \
2665 : : PyDecType_FromUnicodeExact(&PyDec_Type, unicode, context)
2666 : : #define PyDec_FromUnicodeExactWS(unicode, context) \
2667 : : PyDecType_FromUnicodeExactWS(&PyDec_Type, unicode, context)
2668 : :
2669 : : #define PyDec_FromSsize(v, context) \
2670 : : PyDecType_FromSsize(&PyDec_Type, v, context)
2671 : : #define PyDec_FromSsizeExact(v, context) \
2672 : : PyDecType_FromSsizeExact(&PyDec_Type, v, context)
2673 : :
2674 : : #define PyDec_FromLong(pylong, context) \
2675 : : PyDecType_FromLong(&PyDec_Type, pylong, context)
2676 : : #define PyDec_FromLongExact(pylong, context) \
2677 : : PyDecType_FromLongExact(&PyDec_Type, pylong, context)
2678 : :
2679 : : #define PyDec_FromFloat(pyfloat, context) \
2680 : : PyDecType_FromFloat(&PyDec_Type, pyfloat, context)
2681 : : #define PyDec_FromFloatExact(pyfloat, context) \
2682 : : PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context)
2683 : :
2684 : : #define PyDec_FromSequence(sequence, context) \
2685 : : PyDecType_FromSequence(&PyDec_Type, sequence, context)
2686 : : #define PyDec_FromSequenceExact(sequence, context) \
2687 : : PyDecType_FromSequenceExact(&PyDec_Type, sequence, context)
2688 : :
2689 : : /* class method */
2690 : : static PyObject *
2691 : 1223 : dec_from_float(PyObject *type, PyObject *pyfloat)
2692 : : {
2693 : : PyObject *context;
2694 : : PyObject *result;
2695 : :
2696 [ - + ]: 1223 : CURRENT_CONTEXT(context);
2697 : 1223 : result = PyDecType_FromFloatExact(&PyDec_Type, pyfloat, context);
2698 [ + + + + ]: 1223 : if (type != (PyObject *)&PyDec_Type && result != NULL) {
2699 : 210 : Py_SETREF(result, PyObject_CallFunctionObjArgs(type, result, NULL));
2700 : : }
2701 : :
2702 : 1223 : return result;
2703 : : }
2704 : :
2705 : : /* create_decimal_from_float */
2706 : : static PyObject *
2707 : 9 : ctx_from_float(PyObject *context, PyObject *v)
2708 : : {
2709 : 9 : return PyDec_FromFloat(v, context);
2710 : : }
2711 : :
2712 : : /* Apply the context to the input operand. Return a new PyDecObject. */
2713 : : static PyObject *
2714 : 225 : dec_apply(PyObject *v, PyObject *context)
2715 : : {
2716 : : PyObject *result;
2717 : 225 : uint32_t status = 0;
2718 : :
2719 : 225 : result = dec_alloc();
2720 [ - + ]: 225 : if (result == NULL) {
2721 : 0 : return NULL;
2722 : : }
2723 : :
2724 : 225 : mpd_qcopy(MPD(result), MPD(v), &status);
2725 [ - + ]: 225 : if (dec_addstatus(context, status)) {
2726 : 0 : Py_DECREF(result);
2727 : 0 : return NULL;
2728 : : }
2729 : :
2730 : 225 : mpd_qfinalize(MPD(result), CTX(context), &status);
2731 [ - + ]: 225 : if (dec_addstatus(context, status)) {
2732 : 0 : Py_DECREF(result);
2733 : 0 : return NULL;
2734 : : }
2735 : :
2736 : 225 : return result;
2737 : : }
2738 : :
2739 : : /* 'v' can have any type accepted by the Decimal constructor. Attempt
2740 : : an exact conversion. If the result does not meet the restrictions
2741 : : for an mpd_t, fail with InvalidOperation. */
2742 : : static PyObject *
2743 : 196677 : PyDecType_FromObjectExact(PyTypeObject *type, PyObject *v, PyObject *context)
2744 : : {
2745 [ + + ]: 196677 : if (v == NULL) {
2746 : 3 : return PyDecType_FromSsizeExact(type, 0, context);
2747 : : }
2748 [ + + ]: 196674 : else if (PyDec_Check(v)) {
2749 : 3025 : return PyDecType_FromDecimalExact(type, v, context);
2750 : : }
2751 [ + + ]: 193649 : else if (PyUnicode_Check(v)) {
2752 : 131610 : return PyDecType_FromUnicodeExactWS(type, v, context);
2753 : : }
2754 [ + + ]: 62039 : else if (PyLong_Check(v)) {
2755 : 51198 : return PyDecType_FromLongExact(type, v, context);
2756 : : }
2757 [ + + + + ]: 10841 : else if (PyTuple_Check(v) || PyList_Check(v)) {
2758 : 44 : return PyDecType_FromSequenceExact(type, v, context);
2759 : : }
2760 [ + + ]: 10797 : else if (PyFloat_Check(v)) {
2761 [ + + ]: 10758 : if (dec_addstatus(context, MPD_Float_operation)) {
2762 : 1 : return NULL;
2763 : : }
2764 : 10757 : return PyDecType_FromFloatExact(type, v, context);
2765 : : }
2766 : : else {
2767 : 39 : PyErr_Format(PyExc_TypeError,
2768 : : "conversion from %s to Decimal is not supported",
2769 : 39 : Py_TYPE(v)->tp_name);
2770 : 39 : return NULL;
2771 : : }
2772 : : }
2773 : :
2774 : : /* The context is used during conversion. This function is the
2775 : : equivalent of context.create_decimal(). */
2776 : : static PyObject *
2777 : 4193 : PyDec_FromObject(PyObject *v, PyObject *context)
2778 : : {
2779 [ + + ]: 4193 : if (v == NULL) {
2780 : 1 : return PyDec_FromSsize(0, context);
2781 : : }
2782 [ + + ]: 4192 : else if (PyDec_Check(v)) {
2783 : 3 : mpd_context_t *ctx = CTX(context);
2784 [ + + ]: 3 : if (mpd_isnan(MPD(v)) &&
2785 [ + - ]: 2 : MPD(v)->digits > ctx->prec - ctx->clamp) {
2786 : : /* Special case: too many NaN payload digits */
2787 : : PyObject *result;
2788 [ + + ]: 2 : if (dec_addstatus(context, MPD_Conversion_syntax)) {
2789 : 1 : return NULL;
2790 : : }
2791 : 1 : result = dec_alloc();
2792 [ - + ]: 1 : if (result == NULL) {
2793 : 0 : return NULL;
2794 : : }
2795 : 1 : mpd_setspecial(MPD(result), MPD_POS, MPD_NAN);
2796 : 1 : return result;
2797 : : }
2798 : 1 : return dec_apply(v, context);
2799 : : }
2800 [ + + ]: 4189 : else if (PyUnicode_Check(v)) {
2801 : 3957 : return PyDec_FromUnicode(v, context);
2802 : : }
2803 [ + + ]: 232 : else if (PyLong_Check(v)) {
2804 : 12 : return PyDec_FromLong(v, context);
2805 : : }
2806 [ + + + + ]: 220 : else if (PyTuple_Check(v) || PyList_Check(v)) {
2807 : 9 : return PyDec_FromSequence(v, context);
2808 : : }
2809 [ + + ]: 211 : else if (PyFloat_Check(v)) {
2810 [ + + ]: 210 : if (dec_addstatus(context, MPD_Float_operation)) {
2811 : 1 : return NULL;
2812 : : }
2813 : 209 : return PyDec_FromFloat(v, context);
2814 : : }
2815 : : else {
2816 : 1 : PyErr_Format(PyExc_TypeError,
2817 : : "conversion from %s to Decimal is not supported",
2818 : 1 : Py_TYPE(v)->tp_name);
2819 : 1 : return NULL;
2820 : : }
2821 : : }
2822 : :
2823 : : static PyObject *
2824 : 196679 : dec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
2825 : : {
2826 : : static char *kwlist[] = {"value", "context", NULL};
2827 : 196679 : PyObject *v = NULL;
2828 : 196679 : PyObject *context = Py_None;
2829 : :
2830 [ + + ]: 196679 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
2831 : : &v, &context)) {
2832 : 1 : return NULL;
2833 : : }
2834 [ + + - + : 196678 : CONTEXT_CHECK_VA(context);
+ + ]
2835 : :
2836 : 196677 : return PyDecType_FromObjectExact(type, v, context);
2837 : : }
2838 : :
2839 : : static PyObject *
2840 : 4194 : ctx_create_decimal(PyObject *context, PyObject *args)
2841 : : {
2842 : 4194 : PyObject *v = NULL;
2843 : :
2844 [ + + ]: 4194 : if (!PyArg_ParseTuple(args, "|O", &v)) {
2845 : 1 : return NULL;
2846 : : }
2847 : :
2848 : 4193 : return PyDec_FromObject(v, context);
2849 : : }
2850 : :
2851 : :
2852 : : /******************************************************************************/
2853 : : /* Implicit conversions to Decimal */
2854 : : /******************************************************************************/
2855 : :
2856 : : /* Try to convert PyObject v to a new PyDecObject conv. If the conversion
2857 : : fails, set conv to NULL (exception is set). If the conversion is not
2858 : : implemented, set conv to Py_NotImplemented. */
2859 : : #define NOT_IMPL 0
2860 : : #define TYPE_ERR 1
2861 : : Py_LOCAL_INLINE(int)
2862 : 214713 : convert_op(int type_err, PyObject **conv, PyObject *v, PyObject *context)
2863 : : {
2864 : :
2865 [ + + ]: 214713 : if (PyDec_Check(v)) {
2866 : 206387 : *conv = v;
2867 : 206387 : Py_INCREF(v);
2868 : 206387 : return 1;
2869 : : }
2870 [ + + ]: 8326 : if (PyLong_Check(v)) {
2871 : 8202 : *conv = PyDec_FromLongExact(v, context);
2872 [ - + ]: 8202 : if (*conv == NULL) {
2873 : 0 : return 0;
2874 : : }
2875 : 8202 : return 1;
2876 : : }
2877 : :
2878 [ + + ]: 124 : if (type_err) {
2879 : 102 : PyErr_Format(PyExc_TypeError,
2880 : : "conversion from %s to Decimal is not supported",
2881 : 102 : Py_TYPE(v)->tp_name);
2882 : : }
2883 : : else {
2884 : 22 : Py_INCREF(Py_NotImplemented);
2885 : 22 : *conv = Py_NotImplemented;
2886 : : }
2887 : 124 : return 0;
2888 : : }
2889 : :
2890 : : /* Return NotImplemented for unsupported types. */
2891 : : #define CONVERT_OP(a, v, context) \
2892 : : if (!convert_op(NOT_IMPL, a, v, context)) { \
2893 : : return *(a); \
2894 : : }
2895 : :
2896 : : #define CONVERT_BINOP(a, b, v, w, context) \
2897 : : if (!convert_op(NOT_IMPL, a, v, context)) { \
2898 : : return *(a); \
2899 : : } \
2900 : : if (!convert_op(NOT_IMPL, b, w, context)) { \
2901 : : Py_DECREF(*(a)); \
2902 : : return *(b); \
2903 : : }
2904 : :
2905 : : #define CONVERT_TERNOP(a, b, c, v, w, x, context) \
2906 : : if (!convert_op(NOT_IMPL, a, v, context)) { \
2907 : : return *(a); \
2908 : : } \
2909 : : if (!convert_op(NOT_IMPL, b, w, context)) { \
2910 : : Py_DECREF(*(a)); \
2911 : : return *(b); \
2912 : : } \
2913 : : if (!convert_op(NOT_IMPL, c, x, context)) { \
2914 : : Py_DECREF(*(a)); \
2915 : : Py_DECREF(*(b)); \
2916 : : return *(c); \
2917 : : }
2918 : :
2919 : : /* Raise TypeError for unsupported types. */
2920 : : #define CONVERT_OP_RAISE(a, v, context) \
2921 : : if (!convert_op(TYPE_ERR, a, v, context)) { \
2922 : : return NULL; \
2923 : : }
2924 : :
2925 : : #define CONVERT_BINOP_RAISE(a, b, v, w, context) \
2926 : : if (!convert_op(TYPE_ERR, a, v, context)) { \
2927 : : return NULL; \
2928 : : } \
2929 : : if (!convert_op(TYPE_ERR, b, w, context)) { \
2930 : : Py_DECREF(*(a)); \
2931 : : return NULL; \
2932 : : }
2933 : :
2934 : : #define CONVERT_TERNOP_RAISE(a, b, c, v, w, x, context) \
2935 : : if (!convert_op(TYPE_ERR, a, v, context)) { \
2936 : : return NULL; \
2937 : : } \
2938 : : if (!convert_op(TYPE_ERR, b, w, context)) { \
2939 : : Py_DECREF(*(a)); \
2940 : : return NULL; \
2941 : : } \
2942 : : if (!convert_op(TYPE_ERR, c, x, context)) { \
2943 : : Py_DECREF(*(a)); \
2944 : : Py_DECREF(*(b)); \
2945 : : return NULL; \
2946 : : }
2947 : :
2948 : :
2949 : : /******************************************************************************/
2950 : : /* Implicit conversions to Decimal for comparison */
2951 : : /******************************************************************************/
2952 : :
2953 : : /* Convert rationals for comparison */
2954 : : static PyObject *Rational = NULL;
2955 : : static PyObject *
2956 : 73 : multiply_by_denominator(PyObject *v, PyObject *r, PyObject *context)
2957 : : {
2958 : : PyObject *result;
2959 : 73 : PyObject *tmp = NULL;
2960 : 73 : PyObject *denom = NULL;
2961 : 73 : uint32_t status = 0;
2962 : : mpd_context_t maxctx;
2963 : : mpd_ssize_t exp;
2964 : : mpd_t *vv;
2965 : :
2966 : : /* v is not special, r is a rational */
2967 : 73 : tmp = PyObject_GetAttrString(r, "denominator");
2968 [ - + ]: 73 : if (tmp == NULL) {
2969 : 0 : return NULL;
2970 : : }
2971 : 73 : denom = PyDec_FromLongExact(tmp, context);
2972 : 73 : Py_DECREF(tmp);
2973 [ - + ]: 73 : if (denom == NULL) {
2974 : 0 : return NULL;
2975 : : }
2976 : :
2977 : 73 : vv = mpd_qncopy(MPD(v));
2978 [ - + ]: 73 : if (vv == NULL) {
2979 : 0 : Py_DECREF(denom);
2980 : : PyErr_NoMemory();
2981 : 0 : return NULL;
2982 : : }
2983 : 73 : result = dec_alloc();
2984 [ - + ]: 73 : if (result == NULL) {
2985 : 0 : Py_DECREF(denom);
2986 : 0 : mpd_del(vv);
2987 : 0 : return NULL;
2988 : : }
2989 : :
2990 : 73 : mpd_maxcontext(&maxctx);
2991 : : /* Prevent Overflow in the following multiplication. The result of
2992 : : the multiplication is only used in mpd_qcmp, which can handle
2993 : : values that are technically out of bounds, like (for 32-bit)
2994 : : 99999999999999999999...99999999e+425000000. */
2995 : 73 : exp = vv->exp;
2996 : 73 : vv->exp = 0;
2997 : 73 : mpd_qmul(MPD(result), vv, MPD(denom), &maxctx, &status);
2998 : 73 : MPD(result)->exp = exp;
2999 : :
3000 : 73 : Py_DECREF(denom);
3001 : 73 : mpd_del(vv);
3002 : : /* If any status has been accumulated during the multiplication,
3003 : : the result is invalid. This is very unlikely, since even the
3004 : : 32-bit version supports 425000000 digits. */
3005 [ - + ]: 73 : if (status) {
3006 : 0 : PyErr_SetString(PyExc_ValueError,
3007 : : "exact conversion for comparison failed");
3008 : 0 : Py_DECREF(result);
3009 : 0 : return NULL;
3010 : : }
3011 : :
3012 : 73 : return result;
3013 : : }
3014 : :
3015 : : static PyObject *
3016 : 100 : numerator_as_decimal(PyObject *r, PyObject *context)
3017 : : {
3018 : : PyObject *tmp, *num;
3019 : :
3020 : 100 : tmp = PyObject_GetAttrString(r, "numerator");
3021 [ - + ]: 100 : if (tmp == NULL) {
3022 : 0 : return NULL;
3023 : : }
3024 : :
3025 : 100 : num = PyDec_FromLongExact(tmp, context);
3026 : 100 : Py_DECREF(tmp);
3027 : 100 : return num;
3028 : : }
3029 : :
3030 : : /* Convert v and w for comparison. v is a Decimal. If w is a Rational, both
3031 : : v and w have to be transformed. Return 1 for success, with new references
3032 : : to the converted objects in vcmp and wcmp. Return 0 for failure. In that
3033 : : case wcmp is either NULL or Py_NotImplemented (new reference) and vcmp
3034 : : is undefined. */
3035 : : static int
3036 : 20627 : convert_op_cmp(PyObject **vcmp, PyObject **wcmp, PyObject *v, PyObject *w,
3037 : : int op, PyObject *context)
3038 : : {
3039 : 20627 : mpd_context_t *ctx = CTX(context);
3040 : :
3041 : 20627 : *vcmp = v;
3042 : :
3043 [ + + ]: 20627 : if (PyDec_Check(w)) {
3044 : 15356 : Py_INCREF(w);
3045 : 15356 : *wcmp = w;
3046 : : }
3047 [ + + ]: 5271 : else if (PyLong_Check(w)) {
3048 : 3945 : *wcmp = PyDec_FromLongExact(w, context);
3049 : : }
3050 [ + + ]: 1326 : else if (PyFloat_Check(w)) {
3051 [ + + + + : 1309 : if (op != Py_EQ && op != Py_NE &&
+ + ]
3052 : 130 : dec_addstatus(context, MPD_Float_operation)) {
3053 : 5 : *wcmp = NULL;
3054 : : }
3055 : : else {
3056 : 1174 : ctx->status |= MPD_Float_operation;
3057 : 1174 : *wcmp = PyDec_FromFloatExact(w, context);
3058 : : }
3059 : : }
3060 [ + + + + : 161 : else if (PyComplex_Check(w) && (op == Py_EQ || op == Py_NE)) {
+ + ]
3061 : 14 : Py_complex c = PyComplex_AsCComplex(w);
3062 [ - + - - ]: 14 : if (c.real == -1.0 && PyErr_Occurred()) {
3063 : 0 : *wcmp = NULL;
3064 : : }
3065 [ + + ]: 14 : else if (c.imag == 0.0) {
3066 : 10 : PyObject *tmp = PyFloat_FromDouble(c.real);
3067 [ - + ]: 10 : if (tmp == NULL) {
3068 : 0 : *wcmp = NULL;
3069 : : }
3070 : : else {
3071 : 10 : ctx->status |= MPD_Float_operation;
3072 : 10 : *wcmp = PyDec_FromFloatExact(tmp, context);
3073 : 10 : Py_DECREF(tmp);
3074 : : }
3075 : : }
3076 : : else {
3077 : 4 : Py_INCREF(Py_NotImplemented);
3078 : 4 : *wcmp = Py_NotImplemented;
3079 : : }
3080 : : }
3081 : : else {
3082 : 133 : int is_rational = PyObject_IsInstance(w, Rational);
3083 [ - + ]: 133 : if (is_rational < 0) {
3084 : 0 : *wcmp = NULL;
3085 : : }
3086 [ + + ]: 133 : else if (is_rational > 0) {
3087 : 100 : *wcmp = numerator_as_decimal(w, context);
3088 [ + - + + ]: 100 : if (*wcmp && !mpd_isspecial(MPD(v))) {
3089 : 73 : *vcmp = multiply_by_denominator(v, w, context);
3090 [ - + ]: 73 : if (*vcmp == NULL) {
3091 [ # # ]: 0 : Py_CLEAR(*wcmp);
3092 : : }
3093 : : }
3094 : : }
3095 : : else {
3096 : 33 : Py_INCREF(Py_NotImplemented);
3097 : 33 : *wcmp = Py_NotImplemented;
3098 : : }
3099 : : }
3100 : :
3101 [ + + + + ]: 20627 : if (*wcmp == NULL || *wcmp == Py_NotImplemented) {
3102 : 42 : return 0;
3103 : : }
3104 [ + + ]: 20585 : if (*vcmp == v) {
3105 : 20512 : Py_INCREF(v);
3106 : : }
3107 : 20585 : return 1;
3108 : : }
3109 : :
3110 : : #define CONVERT_BINOP_CMP(vcmp, wcmp, v, w, op, ctx) \
3111 : : if (!convert_op_cmp(vcmp, wcmp, v, w, op, ctx)) { \
3112 : : return *(wcmp); \
3113 : : } \
3114 : :
3115 : :
3116 : : /******************************************************************************/
3117 : : /* Conversions from decimal */
3118 : : /******************************************************************************/
3119 : :
3120 : : static PyObject *
3121 : 63893 : unicode_fromascii(const char *s, Py_ssize_t size)
3122 : : {
3123 : : PyObject *res;
3124 : :
3125 : 63893 : res = PyUnicode_New(size, 127);
3126 [ - + ]: 63893 : if (res == NULL) {
3127 : 0 : return NULL;
3128 : : }
3129 : :
3130 : 63893 : memcpy(PyUnicode_1BYTE_DATA(res), s, size);
3131 : 63893 : return res;
3132 : : }
3133 : :
3134 : : /* PyDecObject as a string. The default module context is only used for
3135 : : the value of 'capitals'. */
3136 : : static PyObject *
3137 : 59944 : dec_str(PyObject *dec)
3138 : : {
3139 : : PyObject *res, *context;
3140 : : mpd_ssize_t size;
3141 : : char *cp;
3142 : :
3143 [ - + ]: 59944 : CURRENT_CONTEXT(context);
3144 : 59944 : size = mpd_to_sci_size(&cp, MPD(dec), CtxCaps(context));
3145 [ - + ]: 59944 : if (size < 0) {
3146 : : PyErr_NoMemory();
3147 : 0 : return NULL;
3148 : : }
3149 : :
3150 : 59944 : res = unicode_fromascii(cp, size);
3151 : 59944 : mpd_free(cp);
3152 : 59944 : return res;
3153 : : }
3154 : :
3155 : : /* Representation of a PyDecObject. */
3156 : : static PyObject *
3157 : 4742 : dec_repr(PyObject *dec)
3158 : : {
3159 : : PyObject *res, *context;
3160 : : char *cp;
3161 : :
3162 [ - + ]: 4742 : CURRENT_CONTEXT(context);
3163 : 4742 : cp = mpd_to_sci(MPD(dec), CtxCaps(context));
3164 [ - + ]: 4742 : if (cp == NULL) {
3165 : : PyErr_NoMemory();
3166 : 0 : return NULL;
3167 : : }
3168 : :
3169 : 4742 : res = PyUnicode_FromFormat("Decimal('%s')", cp);
3170 : 4742 : mpd_free(cp);
3171 : 4742 : return res;
3172 : : }
3173 : :
3174 : : /* Return a duplicate of src, copy embedded null characters. */
3175 : : static char *
3176 : 40 : dec_strdup(const char *src, Py_ssize_t size)
3177 : : {
3178 : 40 : char *dest = PyMem_Malloc(size+1);
3179 [ - + ]: 40 : if (dest == NULL) {
3180 : : PyErr_NoMemory();
3181 : 0 : return NULL;
3182 : : }
3183 : :
3184 : 40 : memcpy(dest, src, size);
3185 : 40 : dest[size] = '\0';
3186 : 40 : return dest;
3187 : : }
3188 : :
3189 : : static void
3190 : 4 : dec_replace_fillchar(char *dest)
3191 : : {
3192 [ + + ]: 50 : while (*dest != '\0') {
3193 [ + + ]: 46 : if (*dest == '\xff') *dest = '\0';
3194 : 46 : dest++;
3195 : : }
3196 : 4 : }
3197 : :
3198 : : /* Convert decimal_point or thousands_sep, which may be multibyte or in
3199 : : the range [128, 255], to a UTF8 string. */
3200 : : static PyObject *
3201 : 2 : dotsep_as_utf8(const char *s)
3202 : : {
3203 : : PyObject *utf8;
3204 : : PyObject *tmp;
3205 : : wchar_t buf[2];
3206 : : size_t n;
3207 : :
3208 : 2 : n = mbstowcs(buf, s, 2);
3209 [ - + ]: 2 : if (n != 1) { /* Issue #7442 */
3210 : 0 : PyErr_SetString(PyExc_ValueError,
3211 : : "invalid decimal point or unsupported "
3212 : : "combination of LC_CTYPE and LC_NUMERIC");
3213 : 0 : return NULL;
3214 : : }
3215 : 2 : tmp = PyUnicode_FromWideChar(buf, n);
3216 [ - + ]: 2 : if (tmp == NULL) {
3217 : 0 : return NULL;
3218 : : }
3219 : 2 : utf8 = PyUnicode_AsUTF8String(tmp);
3220 : 2 : Py_DECREF(tmp);
3221 : 2 : return utf8;
3222 : : }
3223 : :
3224 : : /* copy of libmpdec _mpd_round() */
3225 : : static void
3226 : 1 : _mpd_round(mpd_t *result, const mpd_t *a, mpd_ssize_t prec,
3227 : : const mpd_context_t *ctx, uint32_t *status)
3228 : : {
3229 : 1 : mpd_ssize_t exp = a->exp + a->digits - prec;
3230 : :
3231 [ - + ]: 1 : if (prec <= 0) {
3232 : 0 : mpd_seterror(result, MPD_Invalid_operation, status);
3233 : 0 : return;
3234 : : }
3235 [ + - - + ]: 1 : if (mpd_isspecial(a) || mpd_iszero(a)) {
3236 : 0 : mpd_qcopy(result, a, status);
3237 : 0 : return;
3238 : : }
3239 : :
3240 : 1 : mpd_qrescale_fmt(result, a, exp, ctx, status);
3241 [ - + ]: 1 : if (result->digits > prec) {
3242 : 0 : mpd_qrescale_fmt(result, result, exp+1, ctx, status);
3243 : : }
3244 : : }
3245 : :
3246 : : /* Locate negative zero "z" option within a UTF-8 format spec string.
3247 : : * Returns pointer to "z", else NULL.
3248 : : * The portion of the spec we're working with is [[fill]align][sign][z] */
3249 : : static const char *
3250 : 217 : format_spec_z_search(char const *fmt, Py_ssize_t size) {
3251 : 217 : char const *pos = fmt;
3252 : 217 : char const *fmt_end = fmt + size;
3253 : : /* skip over [[fill]align] (fill may be multi-byte character) */
3254 : 217 : pos += 1;
3255 [ + + + + ]: 220 : while (pos < fmt_end && *pos & 0x80) {
3256 : 3 : pos += 1;
3257 : : }
3258 [ + + + + ]: 217 : if (pos < fmt_end && strchr("<>=^", *pos) != NULL) {
3259 : 24 : pos += 1;
3260 : : } else {
3261 : : /* fill not present-- skip over [align] */
3262 : 193 : pos = fmt;
3263 [ + + + + ]: 193 : if (pos < fmt_end && strchr("<>=^", *pos) != NULL) {
3264 : 7 : pos += 1;
3265 : : }
3266 : : }
3267 : : /* skip over [sign] */
3268 [ + + + + ]: 217 : if (pos < fmt_end && strchr("+- ", *pos) != NULL) {
3269 : 17 : pos += 1;
3270 : : }
3271 [ + + + + ]: 217 : return pos < fmt_end && *pos == 'z' ? pos : NULL;
3272 : : }
3273 : :
3274 : : static int
3275 : 102 : dict_get_item_string(PyObject *dict, const char *key, PyObject **valueobj, const char **valuestr)
3276 : : {
3277 : 102 : *valueobj = NULL;
3278 : 102 : PyObject *keyobj = PyUnicode_FromString(key);
3279 [ - + ]: 102 : if (keyobj == NULL) {
3280 : 0 : return -1;
3281 : : }
3282 : 102 : PyObject *value = PyDict_GetItemWithError(dict, keyobj);
3283 : 102 : Py_DECREF(keyobj);
3284 [ - + ]: 102 : if (value == NULL) {
3285 [ # # ]: 0 : if (PyErr_Occurred()) {
3286 : 0 : return -1;
3287 : : }
3288 : 0 : return 0;
3289 : : }
3290 : 102 : value = PyUnicode_AsUTF8String(value);
3291 [ - + ]: 102 : if (value == NULL) {
3292 : 0 : return -1;
3293 : : }
3294 : 102 : *valueobj = value;
3295 : 102 : *valuestr = PyBytes_AS_STRING(value);
3296 : 102 : return 0;
3297 : : }
3298 : :
3299 : : /* Formatted representation of a PyDecObject. */
3300 : : static PyObject *
3301 : 220 : dec_format(PyObject *dec, PyObject *args)
3302 : : {
3303 : 220 : PyObject *result = NULL;
3304 : 220 : PyObject *override = NULL;
3305 : 220 : PyObject *dot = NULL;
3306 : 220 : PyObject *sep = NULL;
3307 : 220 : PyObject *grouping = NULL;
3308 : : PyObject *fmtarg;
3309 : : PyObject *context;
3310 : : mpd_spec_t spec;
3311 : : char const *fmt;
3312 : 220 : char *fmt_copy = NULL;
3313 : 220 : char *decstring = NULL;
3314 : 220 : uint32_t status = 0;
3315 : 220 : int replace_fillchar = 0;
3316 : 220 : int no_neg_0 = 0;
3317 : : Py_ssize_t size;
3318 : 220 : mpd_t *mpd = MPD(dec);
3319 : : mpd_uint_t dt[MPD_MINALLOC_MAX];
3320 : 220 : mpd_t tmp = {MPD_STATIC|MPD_STATIC_DATA,0,0,0,MPD_MINALLOC_MAX,dt};
3321 : :
3322 : :
3323 [ - + ]: 220 : CURRENT_CONTEXT(context);
3324 [ + + ]: 220 : if (!PyArg_ParseTuple(args, "O|O", &fmtarg, &override)) {
3325 : 1 : return NULL;
3326 : : }
3327 : :
3328 [ + + ]: 219 : if (PyUnicode_Check(fmtarg)) {
3329 : 217 : fmt = PyUnicode_AsUTF8AndSize(fmtarg, &size);
3330 [ - + ]: 217 : if (fmt == NULL) {
3331 : 0 : return NULL;
3332 : : }
3333 : : /* NOTE: If https://github.com/python/cpython/pull/29438 lands, the
3334 : : * format string manipulation below can be eliminated by enhancing
3335 : : * the forked mpd_parse_fmt_str(). */
3336 [ + + + + ]: 217 : if (size > 0 && fmt[0] == '\0') {
3337 : : /* NUL fill character: must be replaced with a valid UTF-8 char
3338 : : before calling mpd_parse_fmt_str(). */
3339 : 4 : replace_fillchar = 1;
3340 : 4 : fmt = fmt_copy = dec_strdup(fmt, size);
3341 [ - + ]: 4 : if (fmt_copy == NULL) {
3342 : 0 : return NULL;
3343 : : }
3344 : 4 : fmt_copy[0] = '_';
3345 : : }
3346 : : /* Strip 'z' option, which isn't understood by mpd_parse_fmt_str().
3347 : : * NOTE: fmt is always null terminated by PyUnicode_AsUTF8AndSize() */
3348 : 217 : char const *z_position = format_spec_z_search(fmt, size);
3349 [ + + ]: 217 : if (z_position != NULL) {
3350 : 36 : no_neg_0 = 1;
3351 : 36 : size_t z_index = z_position - fmt;
3352 [ + - ]: 36 : if (fmt_copy == NULL) {
3353 : 36 : fmt = fmt_copy = dec_strdup(fmt, size);
3354 [ - + ]: 36 : if (fmt_copy == NULL) {
3355 : 0 : return NULL;
3356 : : }
3357 : : }
3358 : : /* Shift characters (including null terminator) left,
3359 : : overwriting the 'z' option. */
3360 : 36 : memmove(fmt_copy + z_index, fmt_copy + z_index + 1, size - z_index);
3361 : 36 : size -= 1;
3362 : : }
3363 : : }
3364 : : else {
3365 : 2 : PyErr_SetString(PyExc_TypeError,
3366 : : "format arg must be str");
3367 : 2 : return NULL;
3368 : : }
3369 : :
3370 [ + + ]: 217 : if (!mpd_parse_fmt_str(&spec, fmt, CtxCaps(context))) {
3371 : 2 : PyErr_SetString(PyExc_ValueError,
3372 : : "invalid format string");
3373 : 2 : goto finish;
3374 : : }
3375 [ + + ]: 215 : if (replace_fillchar) {
3376 : : /* In order to avoid clobbering parts of UTF-8 thousands separators or
3377 : : decimal points when the substitution is reversed later, the actual
3378 : : placeholder must be an invalid UTF-8 byte. */
3379 : 4 : spec.fill[0] = '\xff';
3380 : 4 : spec.fill[1] = '\0';
3381 : : }
3382 : :
3383 [ + + ]: 215 : if (override) {
3384 : : /* Values for decimal_point, thousands_sep and grouping can
3385 : : be explicitly specified in the override dict. These values
3386 : : take precedence over the values obtained from localeconv()
3387 : : in mpd_parse_fmt_str(). The feature is not documented and
3388 : : is only used in test_decimal. */
3389 [ + + ]: 35 : if (!PyDict_Check(override)) {
3390 : 1 : PyErr_SetString(PyExc_TypeError,
3391 : : "optional argument must be a dict");
3392 : 1 : goto finish;
3393 : : }
3394 [ + - + - ]: 68 : if (dict_get_item_string(override, "decimal_point", &dot, &spec.dot) ||
3395 [ - + ]: 68 : dict_get_item_string(override, "thousands_sep", &sep, &spec.sep) ||
3396 : 34 : dict_get_item_string(override, "grouping", &grouping, &spec.grouping))
3397 : : {
3398 : 0 : goto finish;
3399 : : }
3400 [ + + ]: 34 : if (mpd_validate_lconv(&spec) < 0) {
3401 : 3 : PyErr_SetString(PyExc_ValueError,
3402 : : "invalid override dict");
3403 : 3 : goto finish;
3404 : : }
3405 : : }
3406 : : else {
3407 : 180 : size_t n = strlen(spec.dot);
3408 [ + + + + : 180 : if (n > 1 || (n == 1 && !isascii((unsigned char)spec.dot[0]))) {
- + ]
3409 : : /* fix locale dependent non-ascii characters */
3410 : 1 : dot = dotsep_as_utf8(spec.dot);
3411 [ - + ]: 1 : if (dot == NULL) {
3412 : 0 : goto finish;
3413 : : }
3414 : 1 : spec.dot = PyBytes_AS_STRING(dot);
3415 : : }
3416 : 180 : n = strlen(spec.sep);
3417 [ + + + + : 180 : if (n > 1 || (n == 1 && !isascii((unsigned char)spec.sep[0]))) {
- + ]
3418 : : /* fix locale dependent non-ascii characters */
3419 : 1 : sep = dotsep_as_utf8(spec.sep);
3420 [ - + ]: 1 : if (sep == NULL) {
3421 : 0 : goto finish;
3422 : : }
3423 : 1 : spec.sep = PyBytes_AS_STRING(sep);
3424 : : }
3425 : : }
3426 : :
3427 [ + + + + : 211 : if (no_neg_0 && mpd_isnegative(mpd) && !mpd_isspecial(mpd)) {
+ - ]
3428 : : /* Round into a temporary (carefully mirroring the rounding
3429 : : of mpd_qformat_spec()), and check if the result is negative zero.
3430 : : If so, clear the sign and format the resulting positive zero. */
3431 : : mpd_ssize_t prec;
3432 : 28 : mpd_qcopy(&tmp, mpd, &status);
3433 [ + + ]: 28 : if (spec.prec >= 0) {
3434 [ + + + + : 27 : switch (spec.type) {
+ ]
3435 : 22 : case 'f':
3436 : 22 : mpd_qrescale(&tmp, &tmp, -spec.prec, CTX(context), &status);
3437 : 22 : break;
3438 : 1 : case '%':
3439 : 1 : tmp.exp += 2;
3440 : 1 : mpd_qrescale(&tmp, &tmp, -spec.prec, CTX(context), &status);
3441 : 1 : break;
3442 : 1 : case 'g':
3443 [ + - ]: 1 : prec = (spec.prec == 0) ? 1 : spec.prec;
3444 [ - + ]: 1 : if (tmp.digits > prec) {
3445 : 0 : _mpd_round(&tmp, &tmp, prec, CTX(context), &status);
3446 : : }
3447 : 1 : break;
3448 : 2 : case 'e':
3449 [ + + ]: 2 : if (!mpd_iszero(&tmp)) {
3450 : 1 : _mpd_round(&tmp, &tmp, spec.prec+1, CTX(context), &status);
3451 : : }
3452 : 2 : break;
3453 : : }
3454 : : }
3455 [ - + ]: 28 : if (status & MPD_Errors) {
3456 : 0 : PyErr_SetString(PyExc_ValueError, "unexpected error when rounding");
3457 : 0 : goto finish;
3458 : : }
3459 [ + + ]: 28 : if (mpd_iszero(&tmp)) {
3460 : 20 : mpd_set_positive(&tmp);
3461 : 20 : mpd = &tmp;
3462 : : }
3463 : : }
3464 : :
3465 : 211 : decstring = mpd_qformat_spec(mpd, &spec, CTX(context), &status);
3466 [ + + ]: 211 : if (decstring == NULL) {
3467 [ - + ]: 1 : if (status & MPD_Malloc_error) {
3468 : : PyErr_NoMemory();
3469 : : }
3470 : : else {
3471 : 1 : PyErr_SetString(PyExc_ValueError,
3472 : : "format specification exceeds internal limits of _decimal");
3473 : : }
3474 : 1 : goto finish;
3475 : : }
3476 : 210 : size = strlen(decstring);
3477 [ + + ]: 210 : if (replace_fillchar) {
3478 : 4 : dec_replace_fillchar(decstring);
3479 : : }
3480 : :
3481 : 210 : result = PyUnicode_DecodeUTF8(decstring, size, NULL);
3482 : :
3483 : :
3484 : 217 : finish:
3485 : 217 : Py_XDECREF(grouping);
3486 : 217 : Py_XDECREF(sep);
3487 : 217 : Py_XDECREF(dot);
3488 [ + + ]: 217 : if (fmt_copy) PyMem_Free(fmt_copy);
3489 [ + + ]: 217 : if (decstring) mpd_free(decstring);
3490 : 217 : return result;
3491 : : }
3492 : :
3493 : : /* Return a PyLongObject from a PyDecObject, using the specified rounding
3494 : : * mode. The context precision is not observed. */
3495 : : static PyObject *
3496 : 22490 : dec_as_long(PyObject *dec, PyObject *context, int round)
3497 : : {
3498 : : PyLongObject *pylong;
3499 : : digit *ob_digit;
3500 : : size_t n;
3501 : : Py_ssize_t i;
3502 : : mpd_t *x;
3503 : : mpd_context_t workctx;
3504 : 22490 : uint32_t status = 0;
3505 : :
3506 [ + + ]: 22490 : if (mpd_isspecial(MPD(dec))) {
3507 [ + + ]: 19 : if (mpd_isnan(MPD(dec))) {
3508 : 11 : PyErr_SetString(PyExc_ValueError,
3509 : : "cannot convert NaN to integer");
3510 : : }
3511 : : else {
3512 : 8 : PyErr_SetString(PyExc_OverflowError,
3513 : : "cannot convert Infinity to integer");
3514 : : }
3515 : 19 : return NULL;
3516 : : }
3517 : :
3518 : 22471 : x = mpd_qnew();
3519 [ - + ]: 22471 : if (x == NULL) {
3520 : : PyErr_NoMemory();
3521 : 0 : return NULL;
3522 : : }
3523 : 22471 : workctx = *CTX(context);
3524 : 22471 : workctx.round = round;
3525 : 22471 : mpd_qround_to_int(x, MPD(dec), &workctx, &status);
3526 [ - + ]: 22471 : if (dec_addstatus(context, status)) {
3527 : 0 : mpd_del(x);
3528 : 0 : return NULL;
3529 : : }
3530 : :
3531 : 22471 : status = 0;
3532 : 22471 : ob_digit = NULL;
3533 : : #if PYLONG_BITS_IN_DIGIT == 30
3534 : 22471 : n = mpd_qexport_u32(&ob_digit, 0, PyLong_BASE, x, &status);
3535 : : #elif PYLONG_BITS_IN_DIGIT == 15
3536 : : n = mpd_qexport_u16(&ob_digit, 0, PyLong_BASE, x, &status);
3537 : : #else
3538 : : #error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
3539 : : #endif
3540 : :
3541 [ - + ]: 22471 : if (n == SIZE_MAX) {
3542 : : PyErr_NoMemory();
3543 : 0 : mpd_del(x);
3544 : 0 : return NULL;
3545 : : }
3546 : :
3547 [ + + ]: 22471 : if (n == 1) {
3548 : 20942 : sdigit val = mpd_arith_sign(x) * ob_digit[0];
3549 : 20942 : mpd_free(ob_digit);
3550 : 20942 : mpd_del(x);
3551 : 20942 : return PyLong_FromLong(val);
3552 : : }
3553 : :
3554 : : assert(n > 0);
3555 : 1529 : pylong = _PyLong_New(n);
3556 [ - + ]: 1529 : if (pylong == NULL) {
3557 : 0 : mpd_free(ob_digit);
3558 : 0 : mpd_del(x);
3559 : 0 : return NULL;
3560 : : }
3561 : :
3562 : 1529 : memcpy(pylong->ob_digit, ob_digit, n * sizeof(digit));
3563 : 1529 : mpd_free(ob_digit);
3564 : :
3565 : 1529 : i = n;
3566 [ + - - + ]: 1529 : while ((i > 0) && (pylong->ob_digit[i-1] == 0)) {
3567 : 0 : i--;
3568 : : }
3569 : :
3570 : 1529 : Py_SET_SIZE(pylong, i);
3571 [ + + + - ]: 1529 : if (mpd_isnegative(x) && !mpd_iszero(x)) {
3572 : 724 : Py_SET_SIZE(pylong, -i);
3573 : : }
3574 : :
3575 : 1529 : mpd_del(x);
3576 : 1529 : return (PyObject *) pylong;
3577 : : }
3578 : :
3579 : : /* Convert a Decimal to its exact integer ratio representation. */
3580 : : static PyObject *
3581 : 12410 : dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
3582 : : {
3583 : 12410 : PyObject *numerator = NULL;
3584 : 12410 : PyObject *denominator = NULL;
3585 : 12410 : PyObject *exponent = NULL;
3586 : 12410 : PyObject *result = NULL;
3587 : : PyObject *tmp;
3588 : : mpd_ssize_t exp;
3589 : : PyObject *context;
3590 : 12410 : uint32_t status = 0;
3591 : :
3592 [ + + ]: 12410 : if (mpd_isspecial(MPD(self))) {
3593 [ + + ]: 39 : if (mpd_isnan(MPD(self))) {
3594 : 15 : PyErr_SetString(PyExc_ValueError,
3595 : : "cannot convert NaN to integer ratio");
3596 : : }
3597 : : else {
3598 : 24 : PyErr_SetString(PyExc_OverflowError,
3599 : : "cannot convert Infinity to integer ratio");
3600 : : }
3601 : 39 : return NULL;
3602 : : }
3603 : :
3604 [ - + ]: 12371 : CURRENT_CONTEXT(context);
3605 : :
3606 : 12371 : tmp = dec_alloc();
3607 [ - + ]: 12371 : if (tmp == NULL) {
3608 : 0 : return NULL;
3609 : : }
3610 : :
3611 [ - + ]: 12371 : if (!mpd_qcopy(MPD(tmp), MPD(self), &status)) {
3612 : 0 : Py_DECREF(tmp);
3613 : : PyErr_NoMemory();
3614 : 0 : return NULL;
3615 : : }
3616 : :
3617 [ + + ]: 12371 : exp = mpd_iszero(MPD(tmp)) ? 0 : MPD(tmp)->exp;
3618 : 12371 : MPD(tmp)->exp = 0;
3619 : :
3620 : : /* context and rounding are unused here: the conversion is exact */
3621 : 12371 : numerator = dec_as_long(tmp, context, MPD_ROUND_FLOOR);
3622 : 12371 : Py_DECREF(tmp);
3623 [ - + ]: 12371 : if (numerator == NULL) {
3624 : 0 : goto error;
3625 : : }
3626 : :
3627 : 12371 : exponent = PyLong_FromSsize_t(exp < 0 ? -exp : exp);
3628 [ - + ]: 12371 : if (exponent == NULL) {
3629 : 0 : goto error;
3630 : : }
3631 : :
3632 : 12371 : tmp = PyLong_FromLong(10);
3633 [ - + ]: 12371 : if (tmp == NULL) {
3634 : 0 : goto error;
3635 : : }
3636 : :
3637 : 12371 : Py_SETREF(exponent, _py_long_power(tmp, exponent, Py_None));
3638 : 12371 : Py_DECREF(tmp);
3639 [ - + ]: 12371 : if (exponent == NULL) {
3640 : 0 : goto error;
3641 : : }
3642 : :
3643 [ + + ]: 12371 : if (exp >= 0) {
3644 : 4110 : Py_SETREF(numerator, _py_long_multiply(numerator, exponent));
3645 [ - + ]: 4110 : if (numerator == NULL) {
3646 : 0 : goto error;
3647 : : }
3648 : 4110 : denominator = PyLong_FromLong(1);
3649 [ - + ]: 4110 : if (denominator == NULL) {
3650 : 0 : goto error;
3651 : : }
3652 : : }
3653 : : else {
3654 : 8261 : denominator = exponent;
3655 : 8261 : exponent = NULL;
3656 : 8261 : tmp = _PyLong_GCD(numerator, denominator);
3657 [ - + ]: 8261 : if (tmp == NULL) {
3658 : 0 : goto error;
3659 : : }
3660 : 8261 : Py_SETREF(numerator, _py_long_floor_divide(numerator, tmp));
3661 : 8261 : Py_SETREF(denominator, _py_long_floor_divide(denominator, tmp));
3662 : 8261 : Py_DECREF(tmp);
3663 [ + - - + ]: 8261 : if (numerator == NULL || denominator == NULL) {
3664 : 0 : goto error;
3665 : : }
3666 : : }
3667 : :
3668 : 12371 : result = PyTuple_Pack(2, numerator, denominator);
3669 : :
3670 : :
3671 : 12371 : error:
3672 : 12371 : Py_XDECREF(exponent);
3673 : 12371 : Py_XDECREF(denominator);
3674 : 12371 : Py_XDECREF(numerator);
3675 : 12371 : return result;
3676 : : }
3677 : :
3678 : : static PyObject *
3679 : 1028 : PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
3680 : : {
3681 : : static char *kwlist[] = {"rounding", "context", NULL};
3682 : : PyObject *result;
3683 : 1028 : PyObject *rounding = Py_None;
3684 : 1028 : PyObject *context = Py_None;
3685 : 1028 : uint32_t status = 0;
3686 : : mpd_context_t workctx;
3687 : :
3688 [ - + ]: 1028 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
3689 : : &rounding, &context)) {
3690 : 0 : return NULL;
3691 : : }
3692 [ + + - + : 1028 : CONTEXT_CHECK_VA(context);
+ + ]
3693 : :
3694 : 1020 : workctx = *CTX(context);
3695 [ + + ]: 1020 : if (rounding != Py_None) {
3696 : 1009 : int round = getround(rounding);
3697 [ + + ]: 1009 : if (round < 0) {
3698 : 4 : return NULL;
3699 : : }
3700 [ - + ]: 1005 : if (!mpd_qsetround(&workctx, round)) {
3701 : 0 : INTERNAL_ERROR_PTR("PyDec_ToIntegralValue"); /* GCOV_NOT_REACHED */
3702 : : }
3703 : : }
3704 : :
3705 : 1016 : result = dec_alloc();
3706 [ - + ]: 1016 : if (result == NULL) {
3707 : 0 : return NULL;
3708 : : }
3709 : :
3710 : 1016 : mpd_qround_to_int(MPD(result), MPD(dec), &workctx, &status);
3711 [ + + ]: 1016 : if (dec_addstatus(context, status)) {
3712 : 2 : Py_DECREF(result);
3713 : 2 : return NULL;
3714 : : }
3715 : :
3716 : 1014 : return result;
3717 : : }
3718 : :
3719 : : static PyObject *
3720 : 16 : PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
3721 : : {
3722 : : static char *kwlist[] = {"rounding", "context", NULL};
3723 : : PyObject *result;
3724 : 16 : PyObject *rounding = Py_None;
3725 : 16 : PyObject *context = Py_None;
3726 : 16 : uint32_t status = 0;
3727 : : mpd_context_t workctx;
3728 : :
3729 [ - + ]: 16 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
3730 : : &rounding, &context)) {
3731 : 0 : return NULL;
3732 : : }
3733 [ + + - + : 16 : CONTEXT_CHECK_VA(context);
+ + ]
3734 : :
3735 : 12 : workctx = *CTX(context);
3736 [ + + ]: 12 : if (rounding != Py_None) {
3737 : 6 : int round = getround(rounding);
3738 [ + + ]: 6 : if (round < 0) {
3739 : 2 : return NULL;
3740 : : }
3741 [ - + ]: 4 : if (!mpd_qsetround(&workctx, round)) {
3742 : 0 : INTERNAL_ERROR_PTR("PyDec_ToIntegralExact"); /* GCOV_NOT_REACHED */
3743 : : }
3744 : : }
3745 : :
3746 : 10 : result = dec_alloc();
3747 [ - + ]: 10 : if (result == NULL) {
3748 : 0 : return NULL;
3749 : : }
3750 : :
3751 : 10 : mpd_qround_to_intx(MPD(result), MPD(dec), &workctx, &status);
3752 [ + + ]: 10 : if (dec_addstatus(context, status)) {
3753 : 2 : Py_DECREF(result);
3754 : 2 : return NULL;
3755 : : }
3756 : :
3757 : 8 : return result;
3758 : : }
3759 : :
3760 : : static PyObject *
3761 : 1489 : PyDec_AsFloat(PyObject *dec)
3762 : : {
3763 : : PyObject *f, *s;
3764 : :
3765 [ + + ]: 1489 : if (mpd_isnan(MPD(dec))) {
3766 [ + + ]: 14 : if (mpd_issnan(MPD(dec))) {
3767 : 4 : PyErr_SetString(PyExc_ValueError,
3768 : : "cannot convert signaling NaN to float");
3769 : 4 : return NULL;
3770 : : }
3771 [ + + ]: 10 : if (mpd_isnegative(MPD(dec))) {
3772 : 2 : s = PyUnicode_FromString("-nan");
3773 : : }
3774 : : else {
3775 : 8 : s = PyUnicode_FromString("nan");
3776 : : }
3777 : : }
3778 : : else {
3779 : 1475 : s = dec_str(dec);
3780 : : }
3781 : :
3782 [ - + ]: 1485 : if (s == NULL) {
3783 : 0 : return NULL;
3784 : : }
3785 : :
3786 : 1485 : f = PyFloat_FromString(s);
3787 : 1485 : Py_DECREF(s);
3788 : :
3789 : 1485 : return f;
3790 : : }
3791 : :
3792 : : static PyObject *
3793 : 52 : PyDec_Round(PyObject *dec, PyObject *args)
3794 : : {
3795 : : PyObject *result;
3796 : 52 : PyObject *x = NULL;
3797 : 52 : uint32_t status = 0;
3798 : : PyObject *context;
3799 : :
3800 : :
3801 [ - + ]: 52 : CURRENT_CONTEXT(context);
3802 [ + + ]: 52 : if (!PyArg_ParseTuple(args, "|O", &x)) {
3803 : 1 : return NULL;
3804 : : }
3805 : :
3806 [ + + ]: 51 : if (x) {
3807 : 24 : mpd_uint_t dq[1] = {1};
3808 : 24 : mpd_t q = {MPD_STATIC|MPD_CONST_DATA,0,1,1,1,dq};
3809 : : mpd_ssize_t y;
3810 : :
3811 [ + + ]: 24 : if (!PyLong_Check(x)) {
3812 : 1 : PyErr_SetString(PyExc_TypeError,
3813 : : "optional arg must be an integer");
3814 : 1 : return NULL;
3815 : : }
3816 : :
3817 : 23 : y = PyLong_AsSsize_t(x);
3818 [ + + + + ]: 23 : if (y == -1 && PyErr_Occurred()) {
3819 : 2 : return NULL;
3820 : : }
3821 : 21 : result = dec_alloc();
3822 [ - + ]: 21 : if (result == NULL) {
3823 : 0 : return NULL;
3824 : : }
3825 : :
3826 [ + + ]: 21 : q.exp = (y == MPD_SSIZE_MIN) ? MPD_SSIZE_MAX : -y;
3827 : 21 : mpd_qquantize(MPD(result), MPD(dec), &q, CTX(context), &status);
3828 [ + + ]: 21 : if (dec_addstatus(context, status)) {
3829 : 4 : Py_DECREF(result);
3830 : 4 : return NULL;
3831 : : }
3832 : :
3833 : 17 : return result;
3834 : : }
3835 : : else {
3836 : 27 : return dec_as_long(dec, context, MPD_ROUND_HALF_EVEN);
3837 : : }
3838 : : }
3839 : :
3840 : : static PyTypeObject *DecimalTuple = NULL;
3841 : : /* Return the DecimalTuple representation of a PyDecObject. */
3842 : : static PyObject *
3843 : 50 : PyDec_AsTuple(PyObject *dec, PyObject *dummy UNUSED)
3844 : : {
3845 : 50 : PyObject *result = NULL;
3846 : 50 : PyObject *sign = NULL;
3847 : 50 : PyObject *coeff = NULL;
3848 : 50 : PyObject *expt = NULL;
3849 : 50 : PyObject *tmp = NULL;
3850 : 50 : mpd_t *x = NULL;
3851 : 50 : char *intstring = NULL;
3852 : : Py_ssize_t intlen, i;
3853 : :
3854 : :
3855 : 50 : x = mpd_qncopy(MPD(dec));
3856 [ - + ]: 50 : if (x == NULL) {
3857 : : PyErr_NoMemory();
3858 : 0 : goto out;
3859 : : }
3860 : :
3861 : 50 : sign = PyLong_FromUnsignedLong(mpd_sign(MPD(dec)));
3862 [ - + ]: 50 : if (sign == NULL) {
3863 : 0 : goto out;
3864 : : }
3865 : :
3866 [ + + ]: 50 : if (mpd_isinfinite(x)) {
3867 : 4 : expt = PyUnicode_FromString("F");
3868 [ - + ]: 4 : if (expt == NULL) {
3869 : 0 : goto out;
3870 : : }
3871 : : /* decimal.py has non-compliant infinity payloads. */
3872 : 4 : coeff = Py_BuildValue("(i)", 0);
3873 [ - + ]: 4 : if (coeff == NULL) {
3874 : 0 : goto out;
3875 : : }
3876 : : }
3877 : : else {
3878 [ + + ]: 46 : if (mpd_isnan(x)) {
3879 [ + + ]: 26 : expt = PyUnicode_FromString(mpd_isqnan(x)?"n":"N");
3880 : : }
3881 : : else {
3882 : 20 : expt = PyLong_FromSsize_t(MPD(dec)->exp);
3883 : : }
3884 [ - + ]: 46 : if (expt == NULL) {
3885 : 0 : goto out;
3886 : : }
3887 : :
3888 : : /* coefficient is defined */
3889 [ + + ]: 46 : if (x->len > 0) {
3890 : :
3891 : : /* make an integer */
3892 : 21 : x->exp = 0;
3893 : : /* clear NaN and sign */
3894 : 21 : mpd_clear_flags(x);
3895 : 21 : intstring = mpd_to_sci(x, 1);
3896 [ - + ]: 21 : if (intstring == NULL) {
3897 : : PyErr_NoMemory();
3898 : 0 : goto out;
3899 : : }
3900 : :
3901 : 21 : intlen = strlen(intstring);
3902 : 21 : coeff = PyTuple_New(intlen);
3903 [ - + ]: 21 : if (coeff == NULL) {
3904 : 0 : goto out;
3905 : : }
3906 : :
3907 [ + + ]: 96 : for (i = 0; i < intlen; i++) {
3908 : 75 : tmp = PyLong_FromLong(intstring[i]-'0');
3909 [ - + ]: 75 : if (tmp == NULL) {
3910 : 0 : goto out;
3911 : : }
3912 : 75 : PyTuple_SET_ITEM(coeff, i, tmp);
3913 : : }
3914 : : }
3915 : : else {
3916 : 25 : coeff = PyTuple_New(0);
3917 [ - + ]: 25 : if (coeff == NULL) {
3918 : 0 : goto out;
3919 : : }
3920 : : }
3921 : : }
3922 : :
3923 : 50 : result = PyObject_CallFunctionObjArgs((PyObject *)DecimalTuple,
3924 : : sign, coeff, expt, NULL);
3925 : :
3926 : 50 : out:
3927 [ + - ]: 50 : if (x) mpd_del(x);
3928 [ + + ]: 50 : if (intstring) mpd_free(intstring);
3929 : 50 : Py_XDECREF(sign);
3930 : 50 : Py_XDECREF(coeff);
3931 : 50 : Py_XDECREF(expt);
3932 : 50 : return result;
3933 : : }
3934 : :
3935 : :
3936 : : /******************************************************************************/
3937 : : /* Macros for converting mpdecimal functions to Decimal methods */
3938 : : /******************************************************************************/
3939 : :
3940 : : /* Unary number method that uses the default module context. */
3941 : : #define Dec_UnaryNumberMethod(MPDFUNC) \
3942 : : static PyObject * \
3943 : : nm_##MPDFUNC(PyObject *self) \
3944 : : { \
3945 : : PyObject *result; \
3946 : : PyObject *context; \
3947 : : uint32_t status = 0; \
3948 : : \
3949 : : CURRENT_CONTEXT(context); \
3950 : : if ((result = dec_alloc()) == NULL) { \
3951 : : return NULL; \
3952 : : } \
3953 : : \
3954 : : MPDFUNC(MPD(result), MPD(self), CTX(context), &status); \
3955 : : if (dec_addstatus(context, status)) { \
3956 : : Py_DECREF(result); \
3957 : : return NULL; \
3958 : : } \
3959 : : \
3960 : : return result; \
3961 : : }
3962 : :
3963 : : /* Binary number method that uses default module context. */
3964 : : #define Dec_BinaryNumberMethod(MPDFUNC) \
3965 : : static PyObject * \
3966 : : nm_##MPDFUNC(PyObject *self, PyObject *other) \
3967 : : { \
3968 : : PyObject *a, *b; \
3969 : : PyObject *result; \
3970 : : PyObject *context; \
3971 : : uint32_t status = 0; \
3972 : : \
3973 : : CURRENT_CONTEXT(context) ; \
3974 : : CONVERT_BINOP(&a, &b, self, other, context); \
3975 : : \
3976 : : if ((result = dec_alloc()) == NULL) { \
3977 : : Py_DECREF(a); \
3978 : : Py_DECREF(b); \
3979 : : return NULL; \
3980 : : } \
3981 : : \
3982 : : MPDFUNC(MPD(result), MPD(a), MPD(b), CTX(context), &status); \
3983 : : Py_DECREF(a); \
3984 : : Py_DECREF(b); \
3985 : : if (dec_addstatus(context, status)) { \
3986 : : Py_DECREF(result); \
3987 : : return NULL; \
3988 : : } \
3989 : : \
3990 : : return result; \
3991 : : }
3992 : :
3993 : : /* Boolean function without a context arg. */
3994 : : #define Dec_BoolFunc(MPDFUNC) \
3995 : : static PyObject * \
3996 : : dec_##MPDFUNC(PyObject *self, PyObject *dummy UNUSED) \
3997 : : { \
3998 : : return MPDFUNC(MPD(self)) ? incr_true() : incr_false(); \
3999 : : }
4000 : :
4001 : : /* Boolean function with an optional context arg. */
4002 : : #define Dec_BoolFuncVA(MPDFUNC) \
4003 : : static PyObject * \
4004 : : dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
4005 : : { \
4006 : : static char *kwlist[] = {"context", NULL}; \
4007 : : PyObject *context = Py_None; \
4008 : : \
4009 : : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, \
4010 : : &context)) { \
4011 : : return NULL; \
4012 : : } \
4013 : : CONTEXT_CHECK_VA(context); \
4014 : : \
4015 : : return MPDFUNC(MPD(self), CTX(context)) ? incr_true() : incr_false(); \
4016 : : }
4017 : :
4018 : : /* Unary function with an optional context arg. */
4019 : : #define Dec_UnaryFuncVA(MPDFUNC) \
4020 : : static PyObject * \
4021 : : dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
4022 : : { \
4023 : : static char *kwlist[] = {"context", NULL}; \
4024 : : PyObject *result; \
4025 : : PyObject *context = Py_None; \
4026 : : uint32_t status = 0; \
4027 : : \
4028 : : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, \
4029 : : &context)) { \
4030 : : return NULL; \
4031 : : } \
4032 : : CONTEXT_CHECK_VA(context); \
4033 : : \
4034 : : if ((result = dec_alloc()) == NULL) { \
4035 : : return NULL; \
4036 : : } \
4037 : : \
4038 : : MPDFUNC(MPD(result), MPD(self), CTX(context), &status); \
4039 : : if (dec_addstatus(context, status)) { \
4040 : : Py_DECREF(result); \
4041 : : return NULL; \
4042 : : } \
4043 : : \
4044 : : return result; \
4045 : : }
4046 : :
4047 : : /* Binary function with an optional context arg. */
4048 : : #define Dec_BinaryFuncVA(MPDFUNC) \
4049 : : static PyObject * \
4050 : : dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
4051 : : { \
4052 : : static char *kwlist[] = {"other", "context", NULL}; \
4053 : : PyObject *other; \
4054 : : PyObject *a, *b; \
4055 : : PyObject *result; \
4056 : : PyObject *context = Py_None; \
4057 : : uint32_t status = 0; \
4058 : : \
4059 : : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, \
4060 : : &other, &context)) { \
4061 : : return NULL; \
4062 : : } \
4063 : : CONTEXT_CHECK_VA(context); \
4064 : : CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
4065 : : \
4066 : : if ((result = dec_alloc()) == NULL) { \
4067 : : Py_DECREF(a); \
4068 : : Py_DECREF(b); \
4069 : : return NULL; \
4070 : : } \
4071 : : \
4072 : : MPDFUNC(MPD(result), MPD(a), MPD(b), CTX(context), &status); \
4073 : : Py_DECREF(a); \
4074 : : Py_DECREF(b); \
4075 : : if (dec_addstatus(context, status)) { \
4076 : : Py_DECREF(result); \
4077 : : return NULL; \
4078 : : } \
4079 : : \
4080 : : return result; \
4081 : : }
4082 : :
4083 : : /* Binary function with an optional context arg. Actual MPDFUNC does
4084 : : NOT take a context. The context is used to record InvalidOperation
4085 : : if the second operand cannot be converted exactly. */
4086 : : #define Dec_BinaryFuncVA_NO_CTX(MPDFUNC) \
4087 : : static PyObject * \
4088 : : dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
4089 : : { \
4090 : : static char *kwlist[] = {"other", "context", NULL}; \
4091 : : PyObject *context = Py_None; \
4092 : : PyObject *other; \
4093 : : PyObject *a, *b; \
4094 : : PyObject *result; \
4095 : : \
4096 : : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, \
4097 : : &other, &context)) { \
4098 : : return NULL; \
4099 : : } \
4100 : : CONTEXT_CHECK_VA(context); \
4101 : : CONVERT_BINOP_RAISE(&a, &b, self, other, context); \
4102 : : \
4103 : : if ((result = dec_alloc()) == NULL) { \
4104 : : Py_DECREF(a); \
4105 : : Py_DECREF(b); \
4106 : : return NULL; \
4107 : : } \
4108 : : \
4109 : : MPDFUNC(MPD(result), MPD(a), MPD(b)); \
4110 : : Py_DECREF(a); \
4111 : : Py_DECREF(b); \
4112 : : \
4113 : : return result; \
4114 : : }
4115 : :
4116 : : /* Ternary function with an optional context arg. */
4117 : : #define Dec_TernaryFuncVA(MPDFUNC) \
4118 : : static PyObject * \
4119 : : dec_##MPDFUNC(PyObject *self, PyObject *args, PyObject *kwds) \
4120 : : { \
4121 : : static char *kwlist[] = {"other", "third", "context", NULL}; \
4122 : : PyObject *other, *third; \
4123 : : PyObject *a, *b, *c; \
4124 : : PyObject *result; \
4125 : : PyObject *context = Py_None; \
4126 : : uint32_t status = 0; \
4127 : : \
4128 : : if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, \
4129 : : &other, &third, &context)) { \
4130 : : return NULL; \
4131 : : } \
4132 : : CONTEXT_CHECK_VA(context); \
4133 : : CONVERT_TERNOP_RAISE(&a, &b, &c, self, other, third, context); \
4134 : : \
4135 : : if ((result = dec_alloc()) == NULL) { \
4136 : : Py_DECREF(a); \
4137 : : Py_DECREF(b); \
4138 : : Py_DECREF(c); \
4139 : : return NULL; \
4140 : : } \
4141 : : \
4142 : : MPDFUNC(MPD(result), MPD(a), MPD(b), MPD(c), CTX(context), &status); \
4143 : : Py_DECREF(a); \
4144 : : Py_DECREF(b); \
4145 : : Py_DECREF(c); \
4146 : : if (dec_addstatus(context, status)) { \
4147 : : Py_DECREF(result); \
4148 : : return NULL; \
4149 : : } \
4150 : : \
4151 : : return result; \
4152 : : }
4153 : :
4154 : :
4155 : : /**********************************************/
4156 : : /* Number methods */
4157 : : /**********************************************/
4158 : :
4159 [ - + - + : 59 : Dec_UnaryNumberMethod(mpd_qminus)
- + ]
4160 [ - + - + : 6 : Dec_UnaryNumberMethod(mpd_qplus)
- + ]
4161 [ - + - + : 520 : Dec_UnaryNumberMethod(mpd_qabs)
- + ]
4162 : :
4163 [ - + + + : 232 : Dec_BinaryNumberMethod(mpd_qadd)
+ + - + +
+ ]
4164 [ - + + + : 202 : Dec_BinaryNumberMethod(mpd_qsub)
+ + - + -
+ ]
4165 [ - + + + : 23934 : Dec_BinaryNumberMethod(mpd_qmul)
+ + - + -
+ ]
4166 [ - + + + : 15130 : Dec_BinaryNumberMethod(mpd_qdiv)
+ + - + +
+ ]
4167 [ - + + + : 9 : Dec_BinaryNumberMethod(mpd_qrem)
+ + - + -
+ ]
4168 [ - + + + : 10 : Dec_BinaryNumberMethod(mpd_qdivint)
+ + - + -
+ ]
4169 : :
4170 : : static PyObject *
4171 : 9564 : nm_dec_as_long(PyObject *dec)
4172 : : {
4173 : : PyObject *context;
4174 : :
4175 [ - + ]: 9564 : CURRENT_CONTEXT(context);
4176 : 9564 : return dec_as_long(dec, context, MPD_ROUND_DOWN);
4177 : : }
4178 : :
4179 : : static int
4180 : 8 : nm_nonzero(PyObject *v)
4181 : : {
4182 : 8 : return !mpd_iszero(MPD(v));
4183 : : }
4184 : :
4185 : : static PyObject *
4186 : 15 : nm_mpd_qdivmod(PyObject *v, PyObject *w)
4187 : : {
4188 : : PyObject *a, *b;
4189 : : PyObject *q, *r;
4190 : : PyObject *context;
4191 : 15 : uint32_t status = 0;
4192 : : PyObject *ret;
4193 : :
4194 [ - + ]: 15 : CURRENT_CONTEXT(context);
4195 [ + + + + ]: 15 : CONVERT_BINOP(&a, &b, v, w, context);
4196 : :
4197 : 13 : q = dec_alloc();
4198 [ - + ]: 13 : if (q == NULL) {
4199 : 0 : Py_DECREF(a);
4200 : 0 : Py_DECREF(b);
4201 : 0 : return NULL;
4202 : : }
4203 : 13 : r = dec_alloc();
4204 [ - + ]: 13 : if (r == NULL) {
4205 : 0 : Py_DECREF(a);
4206 : 0 : Py_DECREF(b);
4207 : 0 : Py_DECREF(q);
4208 : 0 : return NULL;
4209 : : }
4210 : :
4211 : 13 : mpd_qdivmod(MPD(q), MPD(r), MPD(a), MPD(b), CTX(context), &status);
4212 : 13 : Py_DECREF(a);
4213 : 13 : Py_DECREF(b);
4214 [ + + ]: 13 : if (dec_addstatus(context, status)) {
4215 : 2 : Py_DECREF(r);
4216 : 2 : Py_DECREF(q);
4217 : 2 : return NULL;
4218 : : }
4219 : :
4220 : 11 : ret = Py_BuildValue("(OO)", q, r);
4221 : 11 : Py_DECREF(r);
4222 : 11 : Py_DECREF(q);
4223 : 11 : return ret;
4224 : : }
4225 : :
4226 : : static PyObject *
4227 : 88 : nm_mpd_qpow(PyObject *base, PyObject *exp, PyObject *mod)
4228 : : {
4229 : 88 : PyObject *a, *b, *c = NULL;
4230 : : PyObject *result;
4231 : : PyObject *context;
4232 : 88 : uint32_t status = 0;
4233 : :
4234 [ - + ]: 88 : CURRENT_CONTEXT(context);
4235 [ + + + + ]: 88 : CONVERT_BINOP(&a, &b, base, exp, context);
4236 : :
4237 [ + + ]: 86 : if (mod != Py_None) {
4238 [ + + ]: 3 : if (!convert_op(NOT_IMPL, &c, mod, context)) {
4239 : 1 : Py_DECREF(a);
4240 : 1 : Py_DECREF(b);
4241 : 1 : return c;
4242 : : }
4243 : : }
4244 : :
4245 : 85 : result = dec_alloc();
4246 [ - + ]: 85 : if (result == NULL) {
4247 : 0 : Py_DECREF(a);
4248 : 0 : Py_DECREF(b);
4249 : 0 : Py_XDECREF(c);
4250 : 0 : return NULL;
4251 : : }
4252 : :
4253 [ + + ]: 85 : if (c == NULL) {
4254 : 83 : mpd_qpow(MPD(result), MPD(a), MPD(b),
4255 : 83 : CTX(context), &status);
4256 : : }
4257 : : else {
4258 : 2 : mpd_qpowmod(MPD(result), MPD(a), MPD(b), MPD(c),
4259 : 2 : CTX(context), &status);
4260 : 2 : Py_DECREF(c);
4261 : : }
4262 : 85 : Py_DECREF(a);
4263 : 85 : Py_DECREF(b);
4264 [ + + ]: 85 : if (dec_addstatus(context, status)) {
4265 : 1 : Py_DECREF(result);
4266 : 1 : return NULL;
4267 : : }
4268 : :
4269 : 84 : return result;
4270 : : }
4271 : :
4272 : :
4273 : : /******************************************************************************/
4274 : : /* Decimal Methods */
4275 : : /******************************************************************************/
4276 : :
4277 : : /* Unary arithmetic functions, optional context arg */
4278 [ + + + + : 9 : Dec_UnaryFuncVA(mpd_qexp)
- + + + -
+ + + ]
4279 [ + + + + : 9 : Dec_UnaryFuncVA(mpd_qln)
- + + + -
+ + + ]
4280 [ + + + + : 10 : Dec_UnaryFuncVA(mpd_qlog10)
- + + + -
+ + + ]
4281 [ + + + + : 13 : Dec_UnaryFuncVA(mpd_qnext_minus)
- + + + -
+ + + ]
4282 [ + + + + : 14 : Dec_UnaryFuncVA(mpd_qnext_plus)
- + + + -
+ + + ]
4283 [ + + + + : 7 : Dec_UnaryFuncVA(mpd_qreduce)
- + + + -
+ + + ]
4284 [ + + + + : 51 : Dec_UnaryFuncVA(mpd_qsqrt)
- + + + -
+ + + ]
4285 : :
4286 : : /* Binary arithmetic functions, optional context arg */
4287 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qcompare)
- + - + -
+ + + - +
+ + ]
4288 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qcompare_signal)
- + - + -
+ + + - +
+ + ]
4289 [ + + + + : 10 : Dec_BinaryFuncVA(mpd_qmax)
- + - + -
+ + + - +
+ + ]
4290 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qmax_mag)
- + - + -
+ + + - +
+ + ]
4291 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qmin)
- + - + -
+ + + - +
+ + ]
4292 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qmin_mag)
- + - + -
+ + + - +
+ + ]
4293 [ - + + + : 4 : Dec_BinaryFuncVA(mpd_qnext_toward)
- + - + -
+ - + - +
- + ]
4294 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qrem_near)
- + - + -
+ + + - +
+ + ]
4295 : :
4296 : : /* Ternary arithmetic functions, optional context arg */
4297 [ + + + + : 17 : Dec_TernaryFuncVA(mpd_qfma)
- + + + -
+ - + + +
- + + + ]
4298 : :
4299 : : /* Boolean functions, no context arg */
4300 [ + - ]: 2 : Dec_BoolFunc(mpd_iscanonical)
4301 [ + + ]: 43 : Dec_BoolFunc(mpd_isfinite)
4302 [ + + ]: 9 : Dec_BoolFunc(mpd_isinfinite)
4303 [ + + ]: 23 : Dec_BoolFunc(mpd_isnan)
4304 [ + + ]: 4 : Dec_BoolFunc(mpd_isqnan)
4305 [ + + ]: 2 : Dec_BoolFunc(mpd_issnan)
4306 [ + + ]: 2 : Dec_BoolFunc(mpd_issigned)
4307 [ + + ]: 3 : Dec_BoolFunc(mpd_iszero)
4308 : :
4309 : : /* Boolean functions, optional context arg */
4310 [ + + + + : 6 : Dec_BoolFuncVA(mpd_isnormal)
- + + + +
+ ]
4311 [ + + + + : 6 : Dec_BoolFuncVA(mpd_issubnormal)
- + + + +
+ ]
4312 : :
4313 : : /* Unary functions, no context arg */
4314 : : static PyObject *
4315 : 4 : dec_mpd_adjexp(PyObject *self, PyObject *dummy UNUSED)
4316 : : {
4317 : : mpd_ssize_t retval;
4318 : :
4319 [ + + ]: 4 : if (mpd_isspecial(MPD(self))) {
4320 : 2 : retval = 0;
4321 : : }
4322 : : else {
4323 : 2 : retval = mpd_adjexp(MPD(self));
4324 : : }
4325 : :
4326 : 4 : return PyLong_FromSsize_t(retval);
4327 : : }
4328 : :
4329 : : static PyObject *
4330 : 3 : dec_canonical(PyObject *self, PyObject *dummy UNUSED)
4331 : : {
4332 : 3 : Py_INCREF(self);
4333 : 3 : return self;
4334 : : }
4335 : :
4336 : : static PyObject *
4337 : 2 : dec_conjugate(PyObject *self, PyObject *dummy UNUSED)
4338 : : {
4339 : 2 : Py_INCREF(self);
4340 : 2 : return self;
4341 : : }
4342 : :
4343 : : static PyObject *
4344 : 5 : dec_mpd_radix(PyObject *self UNUSED, PyObject *dummy UNUSED)
4345 : : {
4346 : : PyObject *result;
4347 : :
4348 : 5 : result = dec_alloc();
4349 [ - + ]: 5 : if (result == NULL) {
4350 : 0 : return NULL;
4351 : : }
4352 : :
4353 : 5 : _dec_settriple(result, MPD_POS, 10, 0);
4354 : 5 : return result;
4355 : : }
4356 : :
4357 : : static PyObject *
4358 : 2 : dec_mpd_qcopy_abs(PyObject *self, PyObject *dummy UNUSED)
4359 : : {
4360 : : PyObject *result;
4361 : 2 : uint32_t status = 0;
4362 : :
4363 [ - + ]: 2 : if ((result = dec_alloc()) == NULL) {
4364 : 0 : return NULL;
4365 : : }
4366 : :
4367 : 2 : mpd_qcopy_abs(MPD(result), MPD(self), &status);
4368 [ - + ]: 2 : if (status & MPD_Malloc_error) {
4369 : 0 : Py_DECREF(result);
4370 : : PyErr_NoMemory();
4371 : 0 : return NULL;
4372 : : }
4373 : :
4374 : 2 : return result;
4375 : : }
4376 : :
4377 : : static PyObject *
4378 : 2 : dec_mpd_qcopy_negate(PyObject *self, PyObject *dummy UNUSED)
4379 : : {
4380 : : PyObject *result;
4381 : 2 : uint32_t status = 0;
4382 : :
4383 [ - + ]: 2 : if ((result = dec_alloc()) == NULL) {
4384 : 0 : return NULL;
4385 : : }
4386 : :
4387 : 2 : mpd_qcopy_negate(MPD(result), MPD(self), &status);
4388 [ - + ]: 2 : if (status & MPD_Malloc_error) {
4389 : 0 : Py_DECREF(result);
4390 : : PyErr_NoMemory();
4391 : 0 : return NULL;
4392 : : }
4393 : :
4394 : 2 : return result;
4395 : : }
4396 : :
4397 : : /* Unary functions, optional context arg */
4398 [ + + + + : 7 : Dec_UnaryFuncVA(mpd_qinvert)
- + + + -
+ + + ]
4399 [ + + + + : 8 : Dec_UnaryFuncVA(mpd_qlogb)
- + + + -
+ + + ]
4400 : :
4401 : : static PyObject *
4402 : 7 : dec_mpd_class(PyObject *self, PyObject *args, PyObject *kwds)
4403 : : {
4404 : : static char *kwlist[] = {"context", NULL};
4405 : 7 : PyObject *context = Py_None;
4406 : : const char *cp;
4407 : :
4408 [ + + ]: 7 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist,
4409 : : &context)) {
4410 : 2 : return NULL;
4411 : : }
4412 [ + + - + : 5 : CONTEXT_CHECK_VA(context);
+ + ]
4413 : :
4414 : 4 : cp = mpd_class(MPD(self), CTX(context));
4415 : 4 : return PyUnicode_FromString(cp);
4416 : : }
4417 : :
4418 : : static PyObject *
4419 : 6 : dec_mpd_to_eng(PyObject *self, PyObject *args, PyObject *kwds)
4420 : : {
4421 : : static char *kwlist[] = {"context", NULL};
4422 : : PyObject *result;
4423 : 6 : PyObject *context = Py_None;
4424 : : mpd_ssize_t size;
4425 : : char *s;
4426 : :
4427 [ + + ]: 6 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist,
4428 : : &context)) {
4429 : 1 : return NULL;
4430 : : }
4431 [ + + - + : 5 : CONTEXT_CHECK_VA(context);
+ + ]
4432 : :
4433 : 4 : size = mpd_to_eng_size(&s, MPD(self), CtxCaps(context));
4434 [ - + ]: 4 : if (size < 0) {
4435 : : PyErr_NoMemory();
4436 : 0 : return NULL;
4437 : : }
4438 : :
4439 : 4 : result = unicode_fromascii(s, size);
4440 : 4 : mpd_free(s);
4441 : :
4442 : 4 : return result;
4443 : : }
4444 : :
4445 : : /* Binary functions, optional context arg for conversion errors */
4446 [ - + + + : 4 : Dec_BinaryFuncVA_NO_CTX(mpd_compare_total)
- + - + -
+ - + -
+ ]
4447 [ - + + + : 3 : Dec_BinaryFuncVA_NO_CTX(mpd_compare_total_mag)
- + - + -
+ - + -
+ ]
4448 : :
4449 : : static PyObject *
4450 : 6 : dec_mpd_qcopy_sign(PyObject *self, PyObject *args, PyObject *kwds)
4451 : : {
4452 : : static char *kwlist[] = {"other", "context", NULL};
4453 : : PyObject *other;
4454 : : PyObject *a, *b;
4455 : : PyObject *result;
4456 : 6 : PyObject *context = Py_None;
4457 : 6 : uint32_t status = 0;
4458 : :
4459 [ - + ]: 6 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
4460 : : &other, &context)) {
4461 : 0 : return NULL;
4462 : : }
4463 [ + + - + : 6 : CONTEXT_CHECK_VA(context);
- + ]
4464 [ - + + + ]: 6 : CONVERT_BINOP_RAISE(&a, &b, self, other, context);
4465 : :
4466 : 5 : result = dec_alloc();
4467 [ - + ]: 5 : if (result == NULL) {
4468 : 0 : Py_DECREF(a);
4469 : 0 : Py_DECREF(b);
4470 : 0 : return NULL;
4471 : : }
4472 : :
4473 : 5 : mpd_qcopy_sign(MPD(result), MPD(a), MPD(b), &status);
4474 : 5 : Py_DECREF(a);
4475 : 5 : Py_DECREF(b);
4476 [ - + ]: 5 : if (dec_addstatus(context, status)) {
4477 : 0 : Py_DECREF(result);
4478 : 0 : return NULL;
4479 : : }
4480 : :
4481 : 5 : return result;
4482 : : }
4483 : :
4484 : : static PyObject *
4485 : 4 : dec_mpd_same_quantum(PyObject *self, PyObject *args, PyObject *kwds)
4486 : : {
4487 : : static char *kwlist[] = {"other", "context", NULL};
4488 : : PyObject *other;
4489 : : PyObject *a, *b;
4490 : : PyObject *result;
4491 : 4 : PyObject *context = Py_None;
4492 : :
4493 [ + + ]: 4 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist,
4494 : : &other, &context)) {
4495 : 1 : return NULL;
4496 : : }
4497 [ + + - + : 3 : CONTEXT_CHECK_VA(context);
- + ]
4498 [ - + - + ]: 3 : CONVERT_BINOP_RAISE(&a, &b, self, other, context);
4499 : :
4500 [ + - ]: 3 : result = mpd_same_quantum(MPD(a), MPD(b)) ? incr_true() : incr_false();
4501 : 3 : Py_DECREF(a);
4502 : 3 : Py_DECREF(b);
4503 : :
4504 : 3 : return result;
4505 : : }
4506 : :
4507 : : /* Binary functions, optional context arg */
4508 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qand)
- + - + -
+ + + - +
+ + ]
4509 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qor)
- + - + -
+ + + - +
+ + ]
4510 [ - + + + : 6 : Dec_BinaryFuncVA(mpd_qxor)
- + - + -
+ - + - +
+ + ]
4511 : :
4512 [ + + + + : 9 : Dec_BinaryFuncVA(mpd_qrotate)
- + - + -
+ + + - +
+ + ]
4513 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qscaleb)
- + - + -
+ + + - +
+ + ]
4514 [ + + + + : 8 : Dec_BinaryFuncVA(mpd_qshift)
- + - + -
+ + + - +
+ + ]
4515 : :
4516 : : static PyObject *
4517 : 7187 : dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
4518 : : {
4519 : : static char *kwlist[] = {"exp", "rounding", "context", NULL};
4520 : 7187 : PyObject *rounding = Py_None;
4521 : 7187 : PyObject *context = Py_None;
4522 : : PyObject *w, *a, *b;
4523 : : PyObject *result;
4524 : 7187 : uint32_t status = 0;
4525 : : mpd_context_t workctx;
4526 : :
4527 [ + + ]: 7187 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist,
4528 : : &w, &rounding, &context)) {
4529 : 1 : return NULL;
4530 : : }
4531 [ + + - + : 7186 : CONTEXT_CHECK_VA(context);
+ + ]
4532 : :
4533 : 7184 : workctx = *CTX(context);
4534 [ + + ]: 7184 : if (rounding != Py_None) {
4535 : 9 : int round = getround(rounding);
4536 [ + + ]: 9 : if (round < 0) {
4537 : 4 : return NULL;
4538 : : }
4539 [ - + ]: 5 : if (!mpd_qsetround(&workctx, round)) {
4540 : 0 : INTERNAL_ERROR_PTR("dec_mpd_qquantize"); /* GCOV_NOT_REACHED */
4541 : : }
4542 : : }
4543 : :
4544 [ - + - + ]: 7180 : CONVERT_BINOP_RAISE(&a, &b, v, w, context);
4545 : :
4546 : 7180 : result = dec_alloc();
4547 [ - + ]: 7180 : if (result == NULL) {
4548 : 0 : Py_DECREF(a);
4549 : 0 : Py_DECREF(b);
4550 : 0 : return NULL;
4551 : : }
4552 : :
4553 : 7180 : mpd_qquantize(MPD(result), MPD(a), MPD(b), &workctx, &status);
4554 : 7180 : Py_DECREF(a);
4555 : 7180 : Py_DECREF(b);
4556 [ + + ]: 7180 : if (dec_addstatus(context, status)) {
4557 : 3 : Py_DECREF(result);
4558 : 3 : return NULL;
4559 : : }
4560 : :
4561 : 7177 : return result;
4562 : : }
4563 : :
4564 : : /* Special methods */
4565 : : static PyObject *
4566 : 20627 : dec_richcompare(PyObject *v, PyObject *w, int op)
4567 : : {
4568 : : PyObject *a;
4569 : : PyObject *b;
4570 : : PyObject *context;
4571 : 20627 : uint32_t status = 0;
4572 : : int a_issnan, b_issnan;
4573 : : int r;
4574 : :
4575 : : assert(PyDec_Check(v));
4576 : :
4577 [ - + ]: 20627 : CURRENT_CONTEXT(context);
4578 [ + + ]: 20627 : CONVERT_BINOP_CMP(&a, &b, v, w, op, context);
4579 : :
4580 : 20585 : a_issnan = mpd_issnan(MPD(a));
4581 : 20585 : b_issnan = mpd_issnan(MPD(b));
4582 : :
4583 : 20585 : r = mpd_qcmp(MPD(a), MPD(b), &status);
4584 : 20585 : Py_DECREF(a);
4585 : 20585 : Py_DECREF(b);
4586 [ + + ]: 20585 : if (r == INT_MAX) {
4587 : : /* sNaNs or op={le,ge,lt,gt} always signal. */
4588 [ + + + + : 163 : if (a_issnan || b_issnan || (op != Py_EQ && op != Py_NE)) {
+ + + + ]
4589 [ + + ]: 139 : if (dec_addstatus(context, status)) {
4590 : 77 : return NULL;
4591 : : }
4592 : : }
4593 : : /* qNaN comparison with op={eq,ne} or comparison
4594 : : * with InvalidOperation disabled. */
4595 [ + + ]: 86 : return (op == Py_NE) ? incr_true() : incr_false();
4596 : : }
4597 : :
4598 [ + + + + : 20422 : switch (op) {
+ + - ]
4599 : 18252 : case Py_EQ:
4600 : 18252 : r = (r == 0);
4601 : 18252 : break;
4602 : 19 : case Py_NE:
4603 : 19 : r = (r != 0);
4604 : 19 : break;
4605 : 223 : case Py_LE:
4606 : 223 : r = (r <= 0);
4607 : 223 : break;
4608 : 83 : case Py_GE:
4609 : 83 : r = (r >= 0);
4610 : 83 : break;
4611 : 1398 : case Py_LT:
4612 : 1398 : r = (r == -1);
4613 : 1398 : break;
4614 : 447 : case Py_GT:
4615 : 447 : r = (r == 1);
4616 : 447 : break;
4617 : : }
4618 : :
4619 : 20422 : return PyBool_FromLong(r);
4620 : : }
4621 : :
4622 : : /* __ceil__ */
4623 : : static PyObject *
4624 : 14 : dec_ceil(PyObject *self, PyObject *dummy UNUSED)
4625 : : {
4626 : : PyObject *context;
4627 : :
4628 [ - + ]: 14 : CURRENT_CONTEXT(context);
4629 : 14 : return dec_as_long(self, context, MPD_ROUND_CEILING);
4630 : : }
4631 : :
4632 : : /* __complex__ */
4633 : : static PyObject *
4634 : 17 : dec_complex(PyObject *self, PyObject *dummy UNUSED)
4635 : : {
4636 : : PyObject *f;
4637 : : double x;
4638 : :
4639 : 17 : f = PyDec_AsFloat(self);
4640 [ - + ]: 17 : if (f == NULL) {
4641 : 0 : return NULL;
4642 : : }
4643 : :
4644 : 17 : x = PyFloat_AsDouble(f);
4645 : 17 : Py_DECREF(f);
4646 [ - + - - ]: 17 : if (x == -1.0 && PyErr_Occurred()) {
4647 : 0 : return NULL;
4648 : : }
4649 : :
4650 : 17 : return PyComplex_FromDoubles(x, 0);
4651 : : }
4652 : :
4653 : : /* __copy__ and __deepcopy__ */
4654 : : static PyObject *
4655 : 4 : dec_copy(PyObject *self, PyObject *dummy UNUSED)
4656 : : {
4657 : 4 : Py_INCREF(self);
4658 : 4 : return self;
4659 : : }
4660 : :
4661 : : /* __floor__ */
4662 : : static PyObject *
4663 : 14 : dec_floor(PyObject *self, PyObject *dummy UNUSED)
4664 : : {
4665 : : PyObject *context;
4666 : :
4667 [ - + ]: 14 : CURRENT_CONTEXT(context);
4668 : 14 : return dec_as_long(self, context, MPD_ROUND_FLOOR);
4669 : : }
4670 : :
4671 : : /* Always uses the module context */
4672 : : static Py_hash_t
4673 : 5097 : _dec_hash(PyDecObject *v)
4674 : : {
4675 : : #if defined(CONFIG_64) && _PyHASH_BITS == 61
4676 : : /* 2**61 - 1 */
4677 : 5097 : mpd_uint_t p_data[1] = {2305843009213693951ULL};
4678 : 5097 : mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 19, 1, 1, p_data};
4679 : : /* Inverse of 10 modulo p */
4680 : 5097 : mpd_uint_t inv10_p_data[1] = {2075258708292324556ULL};
4681 : 5097 : mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
4682 : : 0, 19, 1, 1, inv10_p_data};
4683 : : #elif defined(CONFIG_32) && _PyHASH_BITS == 31
4684 : : /* 2**31 - 1 */
4685 : : mpd_uint_t p_data[2] = {147483647UL, 2};
4686 : : mpd_t p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA, 0, 10, 2, 2, p_data};
4687 : : /* Inverse of 10 modulo p */
4688 : : mpd_uint_t inv10_p_data[2] = {503238553UL, 1};
4689 : : mpd_t inv10_p = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
4690 : : 0, 10, 2, 2, inv10_p_data};
4691 : : #else
4692 : : #error "No valid combination of CONFIG_64, CONFIG_32 and _PyHASH_BITS"
4693 : : #endif
4694 : 5097 : const Py_hash_t py_hash_inf = 314159;
4695 : 5097 : mpd_uint_t ten_data[1] = {10};
4696 : 5097 : mpd_t ten = {MPD_POS|MPD_STATIC|MPD_CONST_DATA,
4697 : : 0, 2, 1, 1, ten_data};
4698 : : Py_hash_t result;
4699 : 5097 : mpd_t *exp_hash = NULL;
4700 : 5097 : mpd_t *tmp = NULL;
4701 : : mpd_ssize_t exp;
4702 : 5097 : uint32_t status = 0;
4703 : : mpd_context_t maxctx;
4704 : :
4705 : :
4706 [ + + ]: 5097 : if (mpd_isspecial(MPD(v))) {
4707 [ + + ]: 11 : if (mpd_issnan(MPD(v))) {
4708 : 1 : PyErr_SetString(PyExc_TypeError,
4709 : : "Cannot hash a signaling NaN value");
4710 : 1 : return -1;
4711 : : }
4712 [ + + ]: 10 : else if (mpd_isnan(MPD(v))) {
4713 : 4 : return _Py_HashPointer(v);
4714 : : }
4715 : : else {
4716 : 6 : return py_hash_inf * mpd_arith_sign(MPD(v));
4717 : : }
4718 : : }
4719 : :
4720 : 5086 : mpd_maxcontext(&maxctx);
4721 : 5086 : exp_hash = mpd_qnew();
4722 [ - + ]: 5086 : if (exp_hash == NULL) {
4723 : 0 : goto malloc_error;
4724 : : }
4725 : 5086 : tmp = mpd_qnew();
4726 [ - + ]: 5086 : if (tmp == NULL) {
4727 : 0 : goto malloc_error;
4728 : : }
4729 : :
4730 : : /*
4731 : : * exp(v): exponent of v
4732 : : * int(v): coefficient of v
4733 : : */
4734 : 5086 : exp = MPD(v)->exp;
4735 [ + + ]: 5086 : if (exp >= 0) {
4736 : : /* 10**exp(v) % p */
4737 : 4382 : mpd_qsset_ssize(tmp, exp, &maxctx, &status);
4738 : 4382 : mpd_qpowmod(exp_hash, &ten, tmp, &p, &maxctx, &status);
4739 : : }
4740 : : else {
4741 : : /* inv10_p**(-exp(v)) % p */
4742 : 704 : mpd_qsset_ssize(tmp, -exp, &maxctx, &status);
4743 : 704 : mpd_qpowmod(exp_hash, &inv10_p, tmp, &p, &maxctx, &status);
4744 : : }
4745 : :
4746 : : /* hash = (int(v) * exp_hash) % p */
4747 [ - + ]: 5086 : if (!mpd_qcopy(tmp, MPD(v), &status)) {
4748 : 0 : goto malloc_error;
4749 : : }
4750 : 5086 : tmp->exp = 0;
4751 : 5086 : mpd_set_positive(tmp);
4752 : :
4753 : 5086 : maxctx.prec = MPD_MAX_PREC + 21;
4754 : 5086 : maxctx.emax = MPD_MAX_EMAX + 21;
4755 : 5086 : maxctx.emin = MPD_MIN_EMIN - 21;
4756 : :
4757 : 5086 : mpd_qmul(tmp, tmp, exp_hash, &maxctx, &status);
4758 : 5086 : mpd_qrem(tmp, tmp, &p, &maxctx, &status);
4759 : :
4760 : 5086 : result = mpd_qget_ssize(tmp, &status);
4761 [ + + ]: 5086 : result = mpd_ispositive(MPD(v)) ? result : -result;
4762 [ + + ]: 5086 : result = (result == -1) ? -2 : result;
4763 : :
4764 [ + - ]: 5086 : if (status != 0) {
4765 [ # # ]: 0 : if (status & MPD_Malloc_error) {
4766 : 0 : goto malloc_error;
4767 : : }
4768 : : else {
4769 : 0 : PyErr_SetString(PyExc_RuntimeError, /* GCOV_NOT_REACHED */
4770 : : "dec_hash: internal error: please report"); /* GCOV_NOT_REACHED */
4771 : : }
4772 : 0 : result = -1; /* GCOV_NOT_REACHED */
4773 : : }
4774 : :
4775 : :
4776 : 5086 : finish:
4777 [ + - ]: 5086 : if (exp_hash) mpd_del(exp_hash);
4778 [ + - ]: 5086 : if (tmp) mpd_del(tmp);
4779 : 5086 : return result;
4780 : :
4781 : 0 : malloc_error:
4782 : : PyErr_NoMemory();
4783 : 0 : result = -1;
4784 : 0 : goto finish;
4785 : : }
4786 : :
4787 : : static Py_hash_t
4788 : 5768 : dec_hash(PyDecObject *self)
4789 : : {
4790 [ + + ]: 5768 : if (self->hash == -1) {
4791 : 5097 : self->hash = _dec_hash(self);
4792 : : }
4793 : :
4794 : 5768 : return self->hash;
4795 : : }
4796 : :
4797 : : /* __reduce__ */
4798 : : static PyObject *
4799 : 18 : dec_reduce(PyObject *self, PyObject *dummy UNUSED)
4800 : : {
4801 : : PyObject *result, *str;
4802 : :
4803 : 18 : str = dec_str(self);
4804 [ - + ]: 18 : if (str == NULL) {
4805 : 0 : return NULL;
4806 : : }
4807 : :
4808 : 18 : result = Py_BuildValue("O(O)", Py_TYPE(self), str);
4809 : 18 : Py_DECREF(str);
4810 : :
4811 : 18 : return result;
4812 : : }
4813 : :
4814 : : /* __sizeof__ */
4815 : : static PyObject *
4816 : 3 : dec_sizeof(PyObject *v, PyObject *dummy UNUSED)
4817 : : {
4818 : : Py_ssize_t res;
4819 : :
4820 : 3 : res = _PyObject_SIZE(Py_TYPE(v));
4821 [ + + ]: 3 : if (mpd_isdynamic_data(MPD(v))) {
4822 : 2 : res += MPD(v)->alloc * sizeof(mpd_uint_t);
4823 : : }
4824 : 3 : return PyLong_FromSsize_t(res);
4825 : : }
4826 : :
4827 : : /* __trunc__ */
4828 : : static PyObject *
4829 : 500 : dec_trunc(PyObject *self, PyObject *dummy UNUSED)
4830 : : {
4831 : : PyObject *context;
4832 : :
4833 [ - + ]: 500 : CURRENT_CONTEXT(context);
4834 : 500 : return dec_as_long(self, context, MPD_ROUND_DOWN);
4835 : : }
4836 : :
4837 : : /* real and imag */
4838 : : static PyObject *
4839 : 1 : dec_real(PyObject *self, void *closure UNUSED)
4840 : : {
4841 : 1 : Py_INCREF(self);
4842 : 1 : return self;
4843 : : }
4844 : :
4845 : : static PyObject *
4846 : 1 : dec_imag(PyObject *self UNUSED, void *closure UNUSED)
4847 : : {
4848 : : PyObject *result;
4849 : :
4850 : 1 : result = dec_alloc();
4851 [ - + ]: 1 : if (result == NULL) {
4852 : 0 : return NULL;
4853 : : }
4854 : :
4855 : 1 : _dec_settriple(result, MPD_POS, 0, 0);
4856 : 1 : return result;
4857 : : }
4858 : :
4859 : :
4860 : : static PyGetSetDef dec_getsets [] =
4861 : : {
4862 : : { "real", (getter)dec_real, NULL, NULL, NULL},
4863 : : { "imag", (getter)dec_imag, NULL, NULL, NULL},
4864 : : {NULL}
4865 : : };
4866 : :
4867 : : static PyNumberMethods dec_number_methods =
4868 : : {
4869 : : (binaryfunc) nm_mpd_qadd,
4870 : : (binaryfunc) nm_mpd_qsub,
4871 : : (binaryfunc) nm_mpd_qmul,
4872 : : (binaryfunc) nm_mpd_qrem,
4873 : : (binaryfunc) nm_mpd_qdivmod,
4874 : : (ternaryfunc) nm_mpd_qpow,
4875 : : (unaryfunc) nm_mpd_qminus,
4876 : : (unaryfunc) nm_mpd_qplus,
4877 : : (unaryfunc) nm_mpd_qabs,
4878 : : (inquiry) nm_nonzero,
4879 : : (unaryfunc) 0, /* no bit-complement */
4880 : : (binaryfunc) 0, /* no shiftl */
4881 : : (binaryfunc) 0, /* no shiftr */
4882 : : (binaryfunc) 0, /* no bit-and */
4883 : : (binaryfunc) 0, /* no bit-xor */
4884 : : (binaryfunc) 0, /* no bit-ior */
4885 : : (unaryfunc) nm_dec_as_long,
4886 : : 0, /* nb_reserved */
4887 : : (unaryfunc) PyDec_AsFloat,
4888 : : 0, /* binaryfunc nb_inplace_add; */
4889 : : 0, /* binaryfunc nb_inplace_subtract; */
4890 : : 0, /* binaryfunc nb_inplace_multiply; */
4891 : : 0, /* binaryfunc nb_inplace_remainder; */
4892 : : 0, /* ternaryfunc nb_inplace_power; */
4893 : : 0, /* binaryfunc nb_inplace_lshift; */
4894 : : 0, /* binaryfunc nb_inplace_rshift; */
4895 : : 0, /* binaryfunc nb_inplace_and; */
4896 : : 0, /* binaryfunc nb_inplace_xor; */
4897 : : 0, /* binaryfunc nb_inplace_or; */
4898 : : (binaryfunc) nm_mpd_qdivint, /* binaryfunc nb_floor_divide; */
4899 : : (binaryfunc) nm_mpd_qdiv, /* binaryfunc nb_true_divide; */
4900 : : 0, /* binaryfunc nb_inplace_floor_divide; */
4901 : : 0, /* binaryfunc nb_inplace_true_divide; */
4902 : : };
4903 : :
4904 : : static PyMethodDef dec_methods [] =
4905 : : {
4906 : : /* Unary arithmetic functions, optional context arg */
4907 : : { "exp", _PyCFunction_CAST(dec_mpd_qexp), METH_VARARGS|METH_KEYWORDS, doc_exp },
4908 : : { "ln", _PyCFunction_CAST(dec_mpd_qln), METH_VARARGS|METH_KEYWORDS, doc_ln },
4909 : : { "log10", _PyCFunction_CAST(dec_mpd_qlog10), METH_VARARGS|METH_KEYWORDS, doc_log10 },
4910 : : { "next_minus", _PyCFunction_CAST(dec_mpd_qnext_minus), METH_VARARGS|METH_KEYWORDS, doc_next_minus },
4911 : : { "next_plus", _PyCFunction_CAST(dec_mpd_qnext_plus), METH_VARARGS|METH_KEYWORDS, doc_next_plus },
4912 : : { "normalize", _PyCFunction_CAST(dec_mpd_qreduce), METH_VARARGS|METH_KEYWORDS, doc_normalize },
4913 : : { "to_integral", _PyCFunction_CAST(PyDec_ToIntegralValue), METH_VARARGS|METH_KEYWORDS, doc_to_integral },
4914 : : { "to_integral_exact", _PyCFunction_CAST(PyDec_ToIntegralExact), METH_VARARGS|METH_KEYWORDS, doc_to_integral_exact },
4915 : : { "to_integral_value", _PyCFunction_CAST(PyDec_ToIntegralValue), METH_VARARGS|METH_KEYWORDS, doc_to_integral_value },
4916 : : { "sqrt", _PyCFunction_CAST(dec_mpd_qsqrt), METH_VARARGS|METH_KEYWORDS, doc_sqrt },
4917 : :
4918 : : /* Binary arithmetic functions, optional context arg */
4919 : : { "compare", _PyCFunction_CAST(dec_mpd_qcompare), METH_VARARGS|METH_KEYWORDS, doc_compare },
4920 : : { "compare_signal", _PyCFunction_CAST(dec_mpd_qcompare_signal), METH_VARARGS|METH_KEYWORDS, doc_compare_signal },
4921 : : { "max", _PyCFunction_CAST(dec_mpd_qmax), METH_VARARGS|METH_KEYWORDS, doc_max },
4922 : : { "max_mag", _PyCFunction_CAST(dec_mpd_qmax_mag), METH_VARARGS|METH_KEYWORDS, doc_max_mag },
4923 : : { "min", _PyCFunction_CAST(dec_mpd_qmin), METH_VARARGS|METH_KEYWORDS, doc_min },
4924 : : { "min_mag", _PyCFunction_CAST(dec_mpd_qmin_mag), METH_VARARGS|METH_KEYWORDS, doc_min_mag },
4925 : : { "next_toward", _PyCFunction_CAST(dec_mpd_qnext_toward), METH_VARARGS|METH_KEYWORDS, doc_next_toward },
4926 : : { "quantize", _PyCFunction_CAST(dec_mpd_qquantize), METH_VARARGS|METH_KEYWORDS, doc_quantize },
4927 : : { "remainder_near", _PyCFunction_CAST(dec_mpd_qrem_near), METH_VARARGS|METH_KEYWORDS, doc_remainder_near },
4928 : :
4929 : : /* Ternary arithmetic functions, optional context arg */
4930 : : { "fma", _PyCFunction_CAST(dec_mpd_qfma), METH_VARARGS|METH_KEYWORDS, doc_fma },
4931 : :
4932 : : /* Boolean functions, no context arg */
4933 : : { "is_canonical", dec_mpd_iscanonical, METH_NOARGS, doc_is_canonical },
4934 : : { "is_finite", dec_mpd_isfinite, METH_NOARGS, doc_is_finite },
4935 : : { "is_infinite", dec_mpd_isinfinite, METH_NOARGS, doc_is_infinite },
4936 : : { "is_nan", dec_mpd_isnan, METH_NOARGS, doc_is_nan },
4937 : : { "is_qnan", dec_mpd_isqnan, METH_NOARGS, doc_is_qnan },
4938 : : { "is_snan", dec_mpd_issnan, METH_NOARGS, doc_is_snan },
4939 : : { "is_signed", dec_mpd_issigned, METH_NOARGS, doc_is_signed },
4940 : : { "is_zero", dec_mpd_iszero, METH_NOARGS, doc_is_zero },
4941 : :
4942 : : /* Boolean functions, optional context arg */
4943 : : { "is_normal", _PyCFunction_CAST(dec_mpd_isnormal), METH_VARARGS|METH_KEYWORDS, doc_is_normal },
4944 : : { "is_subnormal", _PyCFunction_CAST(dec_mpd_issubnormal), METH_VARARGS|METH_KEYWORDS, doc_is_subnormal },
4945 : :
4946 : : /* Unary functions, no context arg */
4947 : : { "adjusted", dec_mpd_adjexp, METH_NOARGS, doc_adjusted },
4948 : : { "canonical", dec_canonical, METH_NOARGS, doc_canonical },
4949 : : { "conjugate", dec_conjugate, METH_NOARGS, doc_conjugate },
4950 : : { "radix", dec_mpd_radix, METH_NOARGS, doc_radix },
4951 : :
4952 : : /* Unary functions, optional context arg for conversion errors */
4953 : : { "copy_abs", dec_mpd_qcopy_abs, METH_NOARGS, doc_copy_abs },
4954 : : { "copy_negate", dec_mpd_qcopy_negate, METH_NOARGS, doc_copy_negate },
4955 : :
4956 : : /* Unary functions, optional context arg */
4957 : : { "logb", _PyCFunction_CAST(dec_mpd_qlogb), METH_VARARGS|METH_KEYWORDS, doc_logb },
4958 : : { "logical_invert", _PyCFunction_CAST(dec_mpd_qinvert), METH_VARARGS|METH_KEYWORDS, doc_logical_invert },
4959 : : { "number_class", _PyCFunction_CAST(dec_mpd_class), METH_VARARGS|METH_KEYWORDS, doc_number_class },
4960 : : { "to_eng_string", _PyCFunction_CAST(dec_mpd_to_eng), METH_VARARGS|METH_KEYWORDS, doc_to_eng_string },
4961 : :
4962 : : /* Binary functions, optional context arg for conversion errors */
4963 : : { "compare_total", _PyCFunction_CAST(dec_mpd_compare_total), METH_VARARGS|METH_KEYWORDS, doc_compare_total },
4964 : : { "compare_total_mag", _PyCFunction_CAST(dec_mpd_compare_total_mag), METH_VARARGS|METH_KEYWORDS, doc_compare_total_mag },
4965 : : { "copy_sign", _PyCFunction_CAST(dec_mpd_qcopy_sign), METH_VARARGS|METH_KEYWORDS, doc_copy_sign },
4966 : : { "same_quantum", _PyCFunction_CAST(dec_mpd_same_quantum), METH_VARARGS|METH_KEYWORDS, doc_same_quantum },
4967 : :
4968 : : /* Binary functions, optional context arg */
4969 : : { "logical_and", _PyCFunction_CAST(dec_mpd_qand), METH_VARARGS|METH_KEYWORDS, doc_logical_and },
4970 : : { "logical_or", _PyCFunction_CAST(dec_mpd_qor), METH_VARARGS|METH_KEYWORDS, doc_logical_or },
4971 : : { "logical_xor", _PyCFunction_CAST(dec_mpd_qxor), METH_VARARGS|METH_KEYWORDS, doc_logical_xor },
4972 : : { "rotate", _PyCFunction_CAST(dec_mpd_qrotate), METH_VARARGS|METH_KEYWORDS, doc_rotate },
4973 : : { "scaleb", _PyCFunction_CAST(dec_mpd_qscaleb), METH_VARARGS|METH_KEYWORDS, doc_scaleb },
4974 : : { "shift", _PyCFunction_CAST(dec_mpd_qshift), METH_VARARGS|METH_KEYWORDS, doc_shift },
4975 : :
4976 : : /* Miscellaneous */
4977 : : { "from_float", dec_from_float, METH_O|METH_CLASS, doc_from_float },
4978 : : { "as_tuple", PyDec_AsTuple, METH_NOARGS, doc_as_tuple },
4979 : : { "as_integer_ratio", dec_as_integer_ratio, METH_NOARGS, doc_as_integer_ratio },
4980 : :
4981 : : /* Special methods */
4982 : : { "__copy__", dec_copy, METH_NOARGS, NULL },
4983 : : { "__deepcopy__", dec_copy, METH_O, NULL },
4984 : : { "__format__", dec_format, METH_VARARGS, NULL },
4985 : : { "__reduce__", dec_reduce, METH_NOARGS, NULL },
4986 : : { "__round__", PyDec_Round, METH_VARARGS, NULL },
4987 : : { "__ceil__", dec_ceil, METH_NOARGS, NULL },
4988 : : { "__floor__", dec_floor, METH_NOARGS, NULL },
4989 : : { "__trunc__", dec_trunc, METH_NOARGS, NULL },
4990 : : { "__complex__", dec_complex, METH_NOARGS, NULL },
4991 : : { "__sizeof__", dec_sizeof, METH_NOARGS, NULL },
4992 : :
4993 : : { NULL, NULL, 1 }
4994 : : };
4995 : :
4996 : : static PyTypeObject PyDec_Type =
4997 : : {
4998 : : PyVarObject_HEAD_INIT(NULL, 0)
4999 : : "decimal.Decimal", /* tp_name */
5000 : : sizeof(PyDecObject), /* tp_basicsize */
5001 : : 0, /* tp_itemsize */
5002 : : (destructor) dec_dealloc, /* tp_dealloc */
5003 : : 0, /* tp_vectorcall_offset */
5004 : : (getattrfunc) 0, /* tp_getattr */
5005 : : (setattrfunc) 0, /* tp_setattr */
5006 : : 0, /* tp_as_async */
5007 : : (reprfunc) dec_repr, /* tp_repr */
5008 : : &dec_number_methods, /* tp_as_number */
5009 : : 0, /* tp_as_sequence */
5010 : : 0, /* tp_as_mapping */
5011 : : (hashfunc) dec_hash, /* tp_hash */
5012 : : 0, /* tp_call */
5013 : : (reprfunc) dec_str, /* tp_str */
5014 : : (getattrofunc) PyObject_GenericGetAttr, /* tp_getattro */
5015 : : (setattrofunc) 0, /* tp_setattro */
5016 : : (PyBufferProcs *) 0, /* tp_as_buffer */
5017 : : (Py_TPFLAGS_DEFAULT|
5018 : : Py_TPFLAGS_BASETYPE), /* tp_flags */
5019 : : doc_decimal, /* tp_doc */
5020 : : 0, /* tp_traverse */
5021 : : 0, /* tp_clear */
5022 : : dec_richcompare, /* tp_richcompare */
5023 : : 0, /* tp_weaklistoffset */
5024 : : 0, /* tp_iter */
5025 : : 0, /* tp_iternext */
5026 : : dec_methods, /* tp_methods */
5027 : : 0, /* tp_members */
5028 : : dec_getsets, /* tp_getset */
5029 : : 0, /* tp_base */
5030 : : 0, /* tp_dict */
5031 : : 0, /* tp_descr_get */
5032 : : 0, /* tp_descr_set */
5033 : : 0, /* tp_dictoffset */
5034 : : 0, /* tp_init */
5035 : : 0, /* tp_alloc */
5036 : : dec_new, /* tp_new */
5037 : : PyObject_Del, /* tp_free */
5038 : : };
5039 : :
5040 : :
5041 : : /******************************************************************************/
5042 : : /* Context Object, Part 2 */
5043 : : /******************************************************************************/
5044 : :
5045 : :
5046 : : /************************************************************************/
5047 : : /* Macros for converting mpdecimal functions to Context methods */
5048 : : /************************************************************************/
5049 : :
5050 : : /* Boolean context method. */
5051 : : #define DecCtx_BoolFunc(MPDFUNC) \
5052 : : static PyObject * \
5053 : : ctx_##MPDFUNC(PyObject *context, PyObject *v) \
5054 : : { \
5055 : : PyObject *ret; \
5056 : : PyObject *a; \
5057 : : \
5058 : : CONVERT_OP_RAISE(&a, v, context); \
5059 : : \
5060 : : ret = MPDFUNC(MPD(a), CTX(context)) ? incr_true() : incr_false(); \
5061 : : Py_DECREF(a); \
5062 : : return ret; \
5063 : : }
5064 : :
5065 : : /* Boolean context method. MPDFUNC does NOT use a context. */
5066 : : #define DecCtx_BoolFunc_NO_CTX(MPDFUNC) \
5067 : : static PyObject * \
5068 : : ctx_##MPDFUNC(PyObject *context, PyObject *v) \
5069 : : { \
5070 : : PyObject *ret; \
5071 : : PyObject *a; \
5072 : : \
5073 : : CONVERT_OP_RAISE(&a, v, context); \
5074 : : \
5075 : : ret = MPDFUNC(MPD(a)) ? incr_true() : incr_false(); \
5076 : : Py_DECREF(a); \
5077 : : return ret; \
5078 : : }
5079 : :
5080 : : /* Unary context method. */
5081 : : #define DecCtx_UnaryFunc(MPDFUNC) \
5082 : : static PyObject * \
5083 : : ctx_##MPDFUNC(PyObject *context, PyObject *v) \
5084 : : { \
5085 : : PyObject *result, *a; \
5086 : : uint32_t status = 0; \
5087 : : \
5088 : : CONVERT_OP_RAISE(&a, v, context); \
5089 : : \
5090 : : if ((result = dec_alloc()) == NULL) { \
5091 : : Py_DECREF(a); \
5092 : : return NULL; \
5093 : : } \
5094 : : \
5095 : : MPDFUNC(MPD(result), MPD(a), CTX(context), &status); \
5096 : : Py_DECREF(a); \
5097 : : if (dec_addstatus(context, status)) { \
5098 : : Py_DECREF(result); \
5099 : : return NULL; \
5100 : : } \
5101 : : \
5102 : : return result; \
5103 : : }
5104 : :
5105 : : /* Binary context method. */
5106 : : #define DecCtx_BinaryFunc(MPDFUNC) \
5107 : : static PyObject * \
5108 : : ctx_##MPDFUNC(PyObject *context, PyObject *args) \
5109 : : { \
5110 : : PyObject *v, *w; \
5111 : : PyObject *a, *b; \
5112 : : PyObject *result; \
5113 : : uint32_t status = 0; \
5114 : : \
5115 : : if (!PyArg_ParseTuple(args, "OO", &v, &w)) { \
5116 : : return NULL; \
5117 : : } \
5118 : : \
5119 : : CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
5120 : : \
5121 : : if ((result = dec_alloc()) == NULL) { \
5122 : : Py_DECREF(a); \
5123 : : Py_DECREF(b); \
5124 : : return NULL; \
5125 : : } \
5126 : : \
5127 : : MPDFUNC(MPD(result), MPD(a), MPD(b), CTX(context), &status); \
5128 : : Py_DECREF(a); \
5129 : : Py_DECREF(b); \
5130 : : if (dec_addstatus(context, status)) { \
5131 : : Py_DECREF(result); \
5132 : : return NULL; \
5133 : : } \
5134 : : \
5135 : : return result; \
5136 : : }
5137 : :
5138 : : /*
5139 : : * Binary context method. The context is only used for conversion.
5140 : : * The actual MPDFUNC does NOT take a context arg.
5141 : : */
5142 : : #define DecCtx_BinaryFunc_NO_CTX(MPDFUNC) \
5143 : : static PyObject * \
5144 : : ctx_##MPDFUNC(PyObject *context, PyObject *args) \
5145 : : { \
5146 : : PyObject *v, *w; \
5147 : : PyObject *a, *b; \
5148 : : PyObject *result; \
5149 : : \
5150 : : if (!PyArg_ParseTuple(args, "OO", &v, &w)) { \
5151 : : return NULL; \
5152 : : } \
5153 : : \
5154 : : CONVERT_BINOP_RAISE(&a, &b, v, w, context); \
5155 : : \
5156 : : if ((result = dec_alloc()) == NULL) { \
5157 : : Py_DECREF(a); \
5158 : : Py_DECREF(b); \
5159 : : return NULL; \
5160 : : } \
5161 : : \
5162 : : MPDFUNC(MPD(result), MPD(a), MPD(b)); \
5163 : : Py_DECREF(a); \
5164 : : Py_DECREF(b); \
5165 : : \
5166 : : return result; \
5167 : : }
5168 : :
5169 : : /* Ternary context method. */
5170 : : #define DecCtx_TernaryFunc(MPDFUNC) \
5171 : : static PyObject * \
5172 : : ctx_##MPDFUNC(PyObject *context, PyObject *args) \
5173 : : { \
5174 : : PyObject *v, *w, *x; \
5175 : : PyObject *a, *b, *c; \
5176 : : PyObject *result; \
5177 : : uint32_t status = 0; \
5178 : : \
5179 : : if (!PyArg_ParseTuple(args, "OOO", &v, &w, &x)) { \
5180 : : return NULL; \
5181 : : } \
5182 : : \
5183 : : CONVERT_TERNOP_RAISE(&a, &b, &c, v, w, x, context); \
5184 : : \
5185 : : if ((result = dec_alloc()) == NULL) { \
5186 : : Py_DECREF(a); \
5187 : : Py_DECREF(b); \
5188 : : Py_DECREF(c); \
5189 : : return NULL; \
5190 : : } \
5191 : : \
5192 : : MPDFUNC(MPD(result), MPD(a), MPD(b), MPD(c), CTX(context), &status); \
5193 : : Py_DECREF(a); \
5194 : : Py_DECREF(b); \
5195 : : Py_DECREF(c); \
5196 : : if (dec_addstatus(context, status)) { \
5197 : : Py_DECREF(result); \
5198 : : return NULL; \
5199 : : } \
5200 : : \
5201 : : return result; \
5202 : : }
5203 : :
5204 : :
5205 : : /* Unary arithmetic functions */
5206 [ + + - + : 256 : DecCtx_UnaryFunc(mpd_qabs)
- + ]
5207 [ + + - + : 439 : DecCtx_UnaryFunc(mpd_qexp)
- + ]
5208 [ + + - + : 413 : DecCtx_UnaryFunc(mpd_qln)
- + ]
5209 [ + + - + : 388 : DecCtx_UnaryFunc(mpd_qlog10)
- + ]
5210 [ + + - + : 218 : DecCtx_UnaryFunc(mpd_qminus)
- + ]
5211 [ + + - + : 273 : DecCtx_UnaryFunc(mpd_qnext_minus)
- + ]
5212 [ + + - + : 275 : DecCtx_UnaryFunc(mpd_qnext_plus)
- + ]
5213 [ + + - + : 235 : DecCtx_UnaryFunc(mpd_qplus)
- + ]
5214 [ + + - + : 437 : DecCtx_UnaryFunc(mpd_qreduce)
- + ]
5215 [ + + - + : 173 : DecCtx_UnaryFunc(mpd_qround_to_int)
- + ]
5216 [ + + - + : 536 : DecCtx_UnaryFunc(mpd_qround_to_intx)
- + ]
5217 [ + + - + : 3597 : DecCtx_UnaryFunc(mpd_qsqrt)
- + ]
5218 : :
5219 : : /* Binary arithmetic functions */
5220 [ - + + + : 5643 : DecCtx_BinaryFunc(mpd_qadd)
+ + - + +
+ ]
5221 [ - + + + : 2749 : DecCtx_BinaryFunc(mpd_qcompare)
+ + - + +
+ ]
5222 [ - + + + : 1121 : DecCtx_BinaryFunc(mpd_qcompare_signal)
+ + - + -
+ ]
5223 [ - + + + : 3050 : DecCtx_BinaryFunc(mpd_qdiv)
+ + - + +
+ ]
5224 [ - + + + : 1937 : DecCtx_BinaryFunc(mpd_qdivint)
+ + - + -
+ ]
5225 [ - + + + : 846 : DecCtx_BinaryFunc(mpd_qmax)
+ + - + -
+ ]
5226 [ - + + + : 802 : DecCtx_BinaryFunc(mpd_qmax_mag)
+ + - + -
+ ]
5227 [ - + + + : 814 : DecCtx_BinaryFunc(mpd_qmin)
+ + - + -
+ ]
5228 [ - + + + : 772 : DecCtx_BinaryFunc(mpd_qmin_mag)
+ + - + -
+ ]
5229 [ - + + + : 2474 : DecCtx_BinaryFunc(mpd_qmul)
+ + - + +
+ ]
5230 [ - + + + : 950 : DecCtx_BinaryFunc(mpd_qnext_toward)
+ + - + -
+ ]
5231 [ - + + + : 2136 : DecCtx_BinaryFunc(mpd_qquantize)
+ + - + +
+ ]
5232 [ - + + + : 2325 : DecCtx_BinaryFunc(mpd_qrem)
+ + - + -
+ ]
5233 [ - + + + : 1505 : DecCtx_BinaryFunc(mpd_qrem_near)
+ + - + -
+ ]
5234 [ - + + + : 2569 : DecCtx_BinaryFunc(mpd_qsub)
+ + - + -
+ ]
5235 : :
5236 : : static PyObject *
5237 : 10 : ctx_mpd_qdivmod(PyObject *context, PyObject *args)
5238 : : {
5239 : : PyObject *v, *w;
5240 : : PyObject *a, *b;
5241 : : PyObject *q, *r;
5242 : 10 : uint32_t status = 0;
5243 : : PyObject *ret;
5244 : :
5245 [ + + ]: 10 : if (!PyArg_ParseTuple(args, "OO", &v, &w)) {
5246 : 1 : return NULL;
5247 : : }
5248 : :
5249 [ + + + + ]: 9 : CONVERT_BINOP_RAISE(&a, &b, v, w, context);
5250 : :
5251 : 7 : q = dec_alloc();
5252 [ - + ]: 7 : if (q == NULL) {
5253 : 0 : Py_DECREF(a);
5254 : 0 : Py_DECREF(b);
5255 : 0 : return NULL;
5256 : : }
5257 : 7 : r = dec_alloc();
5258 [ - + ]: 7 : if (r == NULL) {
5259 : 0 : Py_DECREF(a);
5260 : 0 : Py_DECREF(b);
5261 : 0 : Py_DECREF(q);
5262 : 0 : return NULL;
5263 : : }
5264 : :
5265 : 7 : mpd_qdivmod(MPD(q), MPD(r), MPD(a), MPD(b), CTX(context), &status);
5266 : 7 : Py_DECREF(a);
5267 : 7 : Py_DECREF(b);
5268 [ + + ]: 7 : if (dec_addstatus(context, status)) {
5269 : 2 : Py_DECREF(r);
5270 : 2 : Py_DECREF(q);
5271 : 2 : return NULL;
5272 : : }
5273 : :
5274 : 5 : ret = Py_BuildValue("(OO)", q, r);
5275 : 5 : Py_DECREF(r);
5276 : 5 : Py_DECREF(q);
5277 : 5 : return ret;
5278 : : }
5279 : :
5280 : : /* Binary or ternary arithmetic functions */
5281 : : static PyObject *
5282 : 5329 : ctx_mpd_qpow(PyObject *context, PyObject *args, PyObject *kwds)
5283 : : {
5284 : : static char *kwlist[] = {"a", "b", "modulo", NULL};
5285 : 5329 : PyObject *base, *exp, *mod = Py_None;
5286 : 5329 : PyObject *a, *b, *c = NULL;
5287 : : PyObject *result;
5288 : 5329 : uint32_t status = 0;
5289 : :
5290 [ + + ]: 5329 : if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist,
5291 : : &base, &exp, &mod)) {
5292 : 3 : return NULL;
5293 : : }
5294 : :
5295 [ + + + + ]: 5326 : CONVERT_BINOP_RAISE(&a, &b, base, exp, context);
5296 : :
5297 [ + + ]: 5324 : if (mod != Py_None) {
5298 [ - + ]: 368 : if (!convert_op(TYPE_ERR, &c, mod, context)) {
5299 : 0 : Py_DECREF(a);
5300 : 0 : Py_DECREF(b);
5301 : 0 : return c;
5302 : : }
5303 : : }
5304 : :
5305 : 5324 : result = dec_alloc();
5306 [ - + ]: 5324 : if (result == NULL) {
5307 : 0 : Py_DECREF(a);
5308 : 0 : Py_DECREF(b);
5309 : 0 : Py_XDECREF(c);
5310 : 0 : return NULL;
5311 : : }
5312 : :
5313 [ + + ]: 5324 : if (c == NULL) {
5314 : 4956 : mpd_qpow(MPD(result), MPD(a), MPD(b),
5315 : 4956 : CTX(context), &status);
5316 : : }
5317 : : else {
5318 : 368 : mpd_qpowmod(MPD(result), MPD(a), MPD(b), MPD(c),
5319 : 368 : CTX(context), &status);
5320 : 368 : Py_DECREF(c);
5321 : : }
5322 : 5324 : Py_DECREF(a);
5323 : 5324 : Py_DECREF(b);
5324 [ + + ]: 5324 : if (dec_addstatus(context, status)) {
5325 : 1 : Py_DECREF(result);
5326 : 1 : return NULL;
5327 : : }
5328 : :
5329 : 5323 : return result;
5330 : : }
5331 : :
5332 : : /* Ternary arithmetic functions */
5333 [ - + + + : 5417 : DecCtx_TernaryFunc(mpd_qfma)
+ + + + -
+ - + ]
5334 : :
5335 : : /* No argument */
5336 : : static PyObject *
5337 : 3 : ctx_mpd_radix(PyObject *context, PyObject *dummy)
5338 : : {
5339 : 3 : return dec_mpd_radix(context, dummy);
5340 : : }
5341 : :
5342 : : /* Boolean functions: single decimal argument */
5343 [ + + + + ]: 214 : DecCtx_BoolFunc(mpd_isnormal)
5344 [ + + + + ]: 214 : DecCtx_BoolFunc(mpd_issubnormal)
5345 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_isfinite)
5346 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_isinfinite)
5347 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_isnan)
5348 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_isqnan)
5349 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_issigned)
5350 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_issnan)
5351 [ + + + + ]: 214 : DecCtx_BoolFunc_NO_CTX(mpd_iszero)
5352 : :
5353 : : static PyObject *
5354 : 212 : ctx_iscanonical(PyObject *context UNUSED, PyObject *v)
5355 : : {
5356 [ + + ]: 212 : if (!PyDec_Check(v)) {
5357 : 1 : PyErr_SetString(PyExc_TypeError,
5358 : : "argument must be a Decimal");
5359 : 1 : return NULL;
5360 : : }
5361 : :
5362 [ + - ]: 211 : return mpd_iscanonical(MPD(v)) ? incr_true() : incr_false();
5363 : : }
5364 : :
5365 : : /* Functions with a single decimal argument */
5366 : : static PyObject *
5367 : 224 : PyDecContext_Apply(PyObject *context, PyObject *v)
5368 : : {
5369 : : PyObject *result, *a;
5370 : :
5371 [ - + ]: 224 : CONVERT_OP_RAISE(&a, v, context);
5372 : :
5373 : 224 : result = dec_apply(a, context);
5374 : 224 : Py_DECREF(a);
5375 : 224 : return result;
5376 : : }
5377 : :
5378 : : static PyObject *
5379 : 4 : ctx_canonical(PyObject *context UNUSED, PyObject *v)
5380 : : {
5381 [ + + ]: 4 : if (!PyDec_Check(v)) {
5382 : 1 : PyErr_SetString(PyExc_TypeError,
5383 : : "argument must be a Decimal");
5384 : 1 : return NULL;
5385 : : }
5386 : :
5387 : 3 : Py_INCREF(v);
5388 : 3 : return v;
5389 : : }
5390 : :
5391 : : static PyObject *
5392 : 134 : ctx_mpd_qcopy_abs(PyObject *context, PyObject *v)
5393 : : {
5394 : : PyObject *result, *a;
5395 : 134 : uint32_t status = 0;
5396 : :
5397 [ + + ]: 134 : CONVERT_OP_RAISE(&a, v, context);
5398 : :
5399 : 133 : result = dec_alloc();
5400 [ - + ]: 133 : if (result == NULL) {
5401 : 0 : Py_DECREF(a);
5402 : 0 : return NULL;
5403 : : }
5404 : :
5405 : 133 : mpd_qcopy_abs(MPD(result), MPD(a), &status);
5406 : 133 : Py_DECREF(a);
5407 [ - + ]: 133 : if (dec_addstatus(context, status)) {
5408 : 0 : Py_DECREF(result);
5409 : 0 : return NULL;
5410 : : }
5411 : :
5412 : 133 : return result;
5413 : : }
5414 : :
5415 : : static PyObject *
5416 : 133 : ctx_copy_decimal(PyObject *context, PyObject *v)
5417 : : {
5418 : : PyObject *result;
5419 : :
5420 [ + + ]: 133 : CONVERT_OP_RAISE(&result, v, context);
5421 : 132 : return result;
5422 : : }
5423 : :
5424 : : static PyObject *
5425 : 134 : ctx_mpd_qcopy_negate(PyObject *context, PyObject *v)
5426 : : {
5427 : : PyObject *result, *a;
5428 : 134 : uint32_t status = 0;
5429 : :
5430 [ + + ]: 134 : CONVERT_OP_RAISE(&a, v, context);
5431 : :
5432 : 133 : result = dec_alloc();
5433 [ - + ]: 133 : if (result == NULL) {
5434 : 0 : Py_DECREF(a);
5435 : 0 : return NULL;
5436 : : }
5437 : :
5438 : 133 : mpd_qcopy_negate(MPD(result), MPD(a), &status);
5439 : 133 : Py_DECREF(a);
5440 [ - + ]: 133 : if (dec_addstatus(context, status)) {
5441 : 0 : Py_DECREF(result);
5442 : 0 : return NULL;
5443 : : }
5444 : :
5445 : 133 : return result;
5446 : : }
5447 : :
5448 [ + + - + : 346 : DecCtx_UnaryFunc(mpd_qlogb)
- + ]
5449 [ + + - + : 476 : DecCtx_UnaryFunc(mpd_qinvert)
- + ]
5450 : :
5451 : : static PyObject *
5452 : 175 : ctx_mpd_class(PyObject *context, PyObject *v)
5453 : : {
5454 : : PyObject *a;
5455 : : const char *cp;
5456 : :
5457 [ - + ]: 175 : CONVERT_OP_RAISE(&a, v, context);
5458 : :
5459 : 175 : cp = mpd_class(MPD(a), CTX(context));
5460 : 175 : Py_DECREF(a);
5461 : :
5462 : 175 : return PyUnicode_FromString(cp);
5463 : : }
5464 : :
5465 : : static PyObject *
5466 : 3303 : ctx_mpd_to_sci(PyObject *context, PyObject *v)
5467 : : {
5468 : : PyObject *result;
5469 : : PyObject *a;
5470 : : mpd_ssize_t size;
5471 : : char *s;
5472 : :
5473 [ + + ]: 3303 : CONVERT_OP_RAISE(&a, v, context);
5474 : :
5475 : 3302 : size = mpd_to_sci_size(&s, MPD(a), CtxCaps(context));
5476 : 3302 : Py_DECREF(a);
5477 [ - + ]: 3302 : if (size < 0) {
5478 : : PyErr_NoMemory();
5479 : 0 : return NULL;
5480 : : }
5481 : :
5482 : 3302 : result = unicode_fromascii(s, size);
5483 : 3302 : mpd_free(s);
5484 : :
5485 : 3302 : return result;
5486 : : }
5487 : :
5488 : : static PyObject *
5489 : 644 : ctx_mpd_to_eng(PyObject *context, PyObject *v)
5490 : : {
5491 : : PyObject *result;
5492 : : PyObject *a;
5493 : : mpd_ssize_t size;
5494 : : char *s;
5495 : :
5496 [ + + ]: 644 : CONVERT_OP_RAISE(&a, v, context);
5497 : :
5498 : 643 : size = mpd_to_eng_size(&s, MPD(a), CtxCaps(context));
5499 : 643 : Py_DECREF(a);
5500 [ - + ]: 643 : if (size < 0) {
5501 : : PyErr_NoMemory();
5502 : 0 : return NULL;
5503 : : }
5504 : :
5505 : 643 : result = unicode_fromascii(s, size);
5506 : 643 : mpd_free(s);
5507 : :
5508 : 643 : return result;
5509 : : }
5510 : :
5511 : : /* Functions with two decimal arguments */
5512 [ - + + + : 1906 : DecCtx_BinaryFunc_NO_CTX(mpd_compare_total)
+ + - + ]
5513 [ - + + + : 1892 : DecCtx_BinaryFunc_NO_CTX(mpd_compare_total_mag)
+ + - + ]
5514 : :
5515 : : static PyObject *
5516 : 334 : ctx_mpd_qcopy_sign(PyObject *context, PyObject *args)
5517 : : {
5518 : : PyObject *v, *w;
5519 : : PyObject *a, *b;
5520 : : PyObject *result;
5521 : 334 : uint32_t status = 0;
5522 : :
5523 [ + + ]: 334 : if (!PyArg_ParseTuple(args, "OO", &v, &w)) {
5524 : 1 : return NULL;
5525 : : }
5526 : :
5527 [ + + + + ]: 333 : CONVERT_BINOP_RAISE(&a, &b, v, w, context);
5528 : :
5529 : 331 : result = dec_alloc();
5530 [ - + ]: 331 : if (result == NULL) {
5531 : 0 : Py_DECREF(a);
5532 : 0 : Py_DECREF(b);
5533 : 0 : return NULL;
5534 : : }
5535 : :
5536 : 331 : mpd_qcopy_sign(MPD(result), MPD(a), MPD(b), &status);
5537 : 331 : Py_DECREF(a);
5538 : 331 : Py_DECREF(b);
5539 [ - + ]: 331 : if (dec_addstatus(context, status)) {
5540 : 0 : Py_DECREF(result);
5541 : 0 : return NULL;
5542 : : }
5543 : :
5544 : 331 : return result;
5545 : : }
5546 : :
5547 [ - + + + : 930 : DecCtx_BinaryFunc(mpd_qand)
+ + - + -
+ ]
5548 [ - + + + : 861 : DecCtx_BinaryFunc(mpd_qor)
+ + - + -
+ ]
5549 [ - + + + : 910 : DecCtx_BinaryFunc(mpd_qxor)
+ + - + -
+ ]
5550 : :
5551 [ - + + + : 673 : DecCtx_BinaryFunc(mpd_qrotate)
+ + - + -
+ ]
5552 [ - + + + : 545 : DecCtx_BinaryFunc(mpd_qscaleb)
+ + - + -
+ ]
5553 [ - + + + : 678 : DecCtx_BinaryFunc(mpd_qshift)
+ + - + -
+ ]
5554 : :
5555 : : static PyObject *
5556 : 1007 : ctx_mpd_same_quantum(PyObject *context, PyObject *args)
5557 : : {
5558 : : PyObject *v, *w;
5559 : : PyObject *a, *b;
5560 : : PyObject *result;
5561 : :
5562 [ + + ]: 1007 : if (!PyArg_ParseTuple(args, "OO", &v, &w)) {
5563 : 1 : return NULL;
5564 : : }
5565 : :
5566 [ + + + + ]: 1006 : CONVERT_BINOP_RAISE(&a, &b, v, w, context);
5567 : :
5568 [ + + ]: 1004 : result = mpd_same_quantum(MPD(a), MPD(b)) ? incr_true() : incr_false();
5569 : 1004 : Py_DECREF(a);
5570 : 1004 : Py_DECREF(b);
5571 : :
5572 : 1004 : return result;
5573 : : }
5574 : :
5575 : :
5576 : : static PyMethodDef context_methods [] =
5577 : : {
5578 : : /* Unary arithmetic functions */
5579 : : { "abs", ctx_mpd_qabs, METH_O, doc_ctx_abs },
5580 : : { "exp", ctx_mpd_qexp, METH_O, doc_ctx_exp },
5581 : : { "ln", ctx_mpd_qln, METH_O, doc_ctx_ln },
5582 : : { "log10", ctx_mpd_qlog10, METH_O, doc_ctx_log10 },
5583 : : { "minus", ctx_mpd_qminus, METH_O, doc_ctx_minus },
5584 : : { "next_minus", ctx_mpd_qnext_minus, METH_O, doc_ctx_next_minus },
5585 : : { "next_plus", ctx_mpd_qnext_plus, METH_O, doc_ctx_next_plus },
5586 : : { "normalize", ctx_mpd_qreduce, METH_O, doc_ctx_normalize },
5587 : : { "plus", ctx_mpd_qplus, METH_O, doc_ctx_plus },
5588 : : { "to_integral", ctx_mpd_qround_to_int, METH_O, doc_ctx_to_integral },
5589 : : { "to_integral_exact", ctx_mpd_qround_to_intx, METH_O, doc_ctx_to_integral_exact },
5590 : : { "to_integral_value", ctx_mpd_qround_to_int, METH_O, doc_ctx_to_integral_value },
5591 : : { "sqrt", ctx_mpd_qsqrt, METH_O, doc_ctx_sqrt },
5592 : :
5593 : : /* Binary arithmetic functions */
5594 : : { "add", ctx_mpd_qadd, METH_VARARGS, doc_ctx_add },
5595 : : { "compare", ctx_mpd_qcompare, METH_VARARGS, doc_ctx_compare },
5596 : : { "compare_signal", ctx_mpd_qcompare_signal, METH_VARARGS, doc_ctx_compare_signal },
5597 : : { "divide", ctx_mpd_qdiv, METH_VARARGS, doc_ctx_divide },
5598 : : { "divide_int", ctx_mpd_qdivint, METH_VARARGS, doc_ctx_divide_int },
5599 : : { "divmod", ctx_mpd_qdivmod, METH_VARARGS, doc_ctx_divmod },
5600 : : { "max", ctx_mpd_qmax, METH_VARARGS, doc_ctx_max },
5601 : : { "max_mag", ctx_mpd_qmax_mag, METH_VARARGS, doc_ctx_max_mag },
5602 : : { "min", ctx_mpd_qmin, METH_VARARGS, doc_ctx_min },
5603 : : { "min_mag", ctx_mpd_qmin_mag, METH_VARARGS, doc_ctx_min_mag },
5604 : : { "multiply", ctx_mpd_qmul, METH_VARARGS, doc_ctx_multiply },
5605 : : { "next_toward", ctx_mpd_qnext_toward, METH_VARARGS, doc_ctx_next_toward },
5606 : : { "quantize", ctx_mpd_qquantize, METH_VARARGS, doc_ctx_quantize },
5607 : : { "remainder", ctx_mpd_qrem, METH_VARARGS, doc_ctx_remainder },
5608 : : { "remainder_near", ctx_mpd_qrem_near, METH_VARARGS, doc_ctx_remainder_near },
5609 : : { "subtract", ctx_mpd_qsub, METH_VARARGS, doc_ctx_subtract },
5610 : :
5611 : : /* Binary or ternary arithmetic functions */
5612 : : { "power", _PyCFunction_CAST(ctx_mpd_qpow), METH_VARARGS|METH_KEYWORDS, doc_ctx_power },
5613 : :
5614 : : /* Ternary arithmetic functions */
5615 : : { "fma", ctx_mpd_qfma, METH_VARARGS, doc_ctx_fma },
5616 : :
5617 : : /* No argument */
5618 : : { "Etiny", context_getetiny, METH_NOARGS, doc_ctx_Etiny },
5619 : : { "Etop", context_getetop, METH_NOARGS, doc_ctx_Etop },
5620 : : { "radix", ctx_mpd_radix, METH_NOARGS, doc_ctx_radix },
5621 : :
5622 : : /* Boolean functions */
5623 : : { "is_canonical", ctx_iscanonical, METH_O, doc_ctx_is_canonical },
5624 : : { "is_finite", ctx_mpd_isfinite, METH_O, doc_ctx_is_finite },
5625 : : { "is_infinite", ctx_mpd_isinfinite, METH_O, doc_ctx_is_infinite },
5626 : : { "is_nan", ctx_mpd_isnan, METH_O, doc_ctx_is_nan },
5627 : : { "is_normal", ctx_mpd_isnormal, METH_O, doc_ctx_is_normal },
5628 : : { "is_qnan", ctx_mpd_isqnan, METH_O, doc_ctx_is_qnan },
5629 : : { "is_signed", ctx_mpd_issigned, METH_O, doc_ctx_is_signed },
5630 : : { "is_snan", ctx_mpd_issnan, METH_O, doc_ctx_is_snan },
5631 : : { "is_subnormal", ctx_mpd_issubnormal, METH_O, doc_ctx_is_subnormal },
5632 : : { "is_zero", ctx_mpd_iszero, METH_O, doc_ctx_is_zero },
5633 : :
5634 : : /* Functions with a single decimal argument */
5635 : : { "_apply", PyDecContext_Apply, METH_O, NULL }, /* alias for apply */
5636 : : #ifdef EXTRA_FUNCTIONALITY
5637 : : { "apply", PyDecContext_Apply, METH_O, doc_ctx_apply },
5638 : : #endif
5639 : : { "canonical", ctx_canonical, METH_O, doc_ctx_canonical },
5640 : : { "copy_abs", ctx_mpd_qcopy_abs, METH_O, doc_ctx_copy_abs },
5641 : : { "copy_decimal", ctx_copy_decimal, METH_O, doc_ctx_copy_decimal },
5642 : : { "copy_negate", ctx_mpd_qcopy_negate, METH_O, doc_ctx_copy_negate },
5643 : : { "logb", ctx_mpd_qlogb, METH_O, doc_ctx_logb },
5644 : : { "logical_invert", ctx_mpd_qinvert, METH_O, doc_ctx_logical_invert },
5645 : : { "number_class", ctx_mpd_class, METH_O, doc_ctx_number_class },
5646 : : { "to_sci_string", ctx_mpd_to_sci, METH_O, doc_ctx_to_sci_string },
5647 : : { "to_eng_string", ctx_mpd_to_eng, METH_O, doc_ctx_to_eng_string },
5648 : :
5649 : : /* Functions with two decimal arguments */
5650 : : { "compare_total", ctx_mpd_compare_total, METH_VARARGS, doc_ctx_compare_total },
5651 : : { "compare_total_mag", ctx_mpd_compare_total_mag, METH_VARARGS, doc_ctx_compare_total_mag },
5652 : : { "copy_sign", ctx_mpd_qcopy_sign, METH_VARARGS, doc_ctx_copy_sign },
5653 : : { "logical_and", ctx_mpd_qand, METH_VARARGS, doc_ctx_logical_and },
5654 : : { "logical_or", ctx_mpd_qor, METH_VARARGS, doc_ctx_logical_or },
5655 : : { "logical_xor", ctx_mpd_qxor, METH_VARARGS, doc_ctx_logical_xor },
5656 : : { "rotate", ctx_mpd_qrotate, METH_VARARGS, doc_ctx_rotate },
5657 : : { "same_quantum", ctx_mpd_same_quantum, METH_VARARGS, doc_ctx_same_quantum },
5658 : : { "scaleb", ctx_mpd_qscaleb, METH_VARARGS, doc_ctx_scaleb },
5659 : : { "shift", ctx_mpd_qshift, METH_VARARGS, doc_ctx_shift },
5660 : :
5661 : : /* Set context values */
5662 : : { "clear_flags", context_clear_flags, METH_NOARGS, doc_ctx_clear_flags },
5663 : : { "clear_traps", context_clear_traps, METH_NOARGS, doc_ctx_clear_traps },
5664 : :
5665 : : #ifdef CONFIG_32
5666 : : /* Unsafe set functions with relaxed range checks */
5667 : : { "_unsafe_setprec", context_unsafe_setprec, METH_O, NULL },
5668 : : { "_unsafe_setemin", context_unsafe_setemin, METH_O, NULL },
5669 : : { "_unsafe_setemax", context_unsafe_setemax, METH_O, NULL },
5670 : : #endif
5671 : :
5672 : : /* Miscellaneous */
5673 : : { "__copy__", (PyCFunction)context_copy, METH_NOARGS, NULL },
5674 : : { "__reduce__", context_reduce, METH_NOARGS, NULL },
5675 : : { "copy", (PyCFunction)context_copy, METH_NOARGS, doc_ctx_copy },
5676 : : { "create_decimal", ctx_create_decimal, METH_VARARGS, doc_ctx_create_decimal },
5677 : : { "create_decimal_from_float", ctx_from_float, METH_O, doc_ctx_create_decimal_from_float },
5678 : :
5679 : : { NULL, NULL, 1 }
5680 : : };
5681 : :
5682 : : static PyTypeObject PyDecContext_Type =
5683 : : {
5684 : : PyVarObject_HEAD_INIT(NULL, 0)
5685 : : "decimal.Context", /* tp_name */
5686 : : sizeof(PyDecContextObject), /* tp_basicsize */
5687 : : 0, /* tp_itemsize */
5688 : : (destructor) context_dealloc, /* tp_dealloc */
5689 : : 0, /* tp_vectorcall_offset */
5690 : : (getattrfunc) 0, /* tp_getattr */
5691 : : (setattrfunc) 0, /* tp_setattr */
5692 : : 0, /* tp_as_async */
5693 : : (reprfunc) context_repr, /* tp_repr */
5694 : : 0, /* tp_as_number */
5695 : : 0, /* tp_as_sequence */
5696 : : 0, /* tp_as_mapping */
5697 : : (hashfunc) 0, /* tp_hash */
5698 : : 0, /* tp_call */
5699 : : 0, /* tp_str */
5700 : : (getattrofunc) context_getattr, /* tp_getattro */
5701 : : (setattrofunc) context_setattr, /* tp_setattro */
5702 : : (PyBufferProcs *) 0, /* tp_as_buffer */
5703 : : Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
5704 : : doc_context, /* tp_doc */
5705 : : 0, /* tp_traverse */
5706 : : 0, /* tp_clear */
5707 : : 0, /* tp_richcompare */
5708 : : 0, /* tp_weaklistoffset */
5709 : : 0, /* tp_iter */
5710 : : 0, /* tp_iternext */
5711 : : context_methods, /* tp_methods */
5712 : : 0, /* tp_members */
5713 : : context_getsets, /* tp_getset */
5714 : : 0, /* tp_base */
5715 : : 0, /* tp_dict */
5716 : : 0, /* tp_descr_get */
5717 : : 0, /* tp_descr_set */
5718 : : 0, /* tp_dictoffset */
5719 : : context_init, /* tp_init */
5720 : : 0, /* tp_alloc */
5721 : : context_new, /* tp_new */
5722 : : PyObject_Del, /* tp_free */
5723 : : };
5724 : :
5725 : :
5726 : : static PyMethodDef _decimal_methods [] =
5727 : : {
5728 : : { "getcontext", (PyCFunction)PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext},
5729 : : { "setcontext", (PyCFunction)PyDec_SetCurrentContext, METH_O, doc_setcontext},
5730 : : { "localcontext", _PyCFunction_CAST(ctxmanager_new), METH_VARARGS|METH_KEYWORDS, doc_localcontext},
5731 : : #ifdef EXTRA_FUNCTIONALITY
5732 : : { "IEEEContext", (PyCFunction)ieee_context, METH_O, doc_ieee_context},
5733 : : #endif
5734 : : { NULL, NULL, 1, NULL }
5735 : : };
5736 : :
5737 : : static struct PyModuleDef _decimal_module = {
5738 : : PyModuleDef_HEAD_INIT,
5739 : : "decimal",
5740 : : doc__decimal,
5741 : : -1,
5742 : : _decimal_methods,
5743 : : NULL,
5744 : : NULL,
5745 : : NULL,
5746 : : NULL
5747 : : };
5748 : :
5749 : : struct ssize_constmap { const char *name; mpd_ssize_t val; };
5750 : : static struct ssize_constmap ssize_constants [] = {
5751 : : {"MAX_PREC", MPD_MAX_PREC},
5752 : : {"MAX_EMAX", MPD_MAX_EMAX},
5753 : : {"MIN_EMIN", MPD_MIN_EMIN},
5754 : : {"MIN_ETINY", MPD_MIN_ETINY},
5755 : : {NULL}
5756 : : };
5757 : :
5758 : : struct int_constmap { const char *name; int val; };
5759 : : static struct int_constmap int_constants [] = {
5760 : : /* int constants */
5761 : : #ifdef EXTRA_FUNCTIONALITY
5762 : : {"DECIMAL32", MPD_DECIMAL32},
5763 : : {"DECIMAL64", MPD_DECIMAL64},
5764 : : {"DECIMAL128", MPD_DECIMAL128},
5765 : : {"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
5766 : : /* int condition flags */
5767 : : {"DecClamped", MPD_Clamped},
5768 : : {"DecConversionSyntax", MPD_Conversion_syntax},
5769 : : {"DecDivisionByZero", MPD_Division_by_zero},
5770 : : {"DecDivisionImpossible", MPD_Division_impossible},
5771 : : {"DecDivisionUndefined", MPD_Division_undefined},
5772 : : {"DecFpuError", MPD_Fpu_error},
5773 : : {"DecInexact", MPD_Inexact},
5774 : : {"DecInvalidContext", MPD_Invalid_context},
5775 : : {"DecInvalidOperation", MPD_Invalid_operation},
5776 : : {"DecIEEEInvalidOperation", MPD_IEEE_Invalid_operation},
5777 : : {"DecMallocError", MPD_Malloc_error},
5778 : : {"DecFloatOperation", MPD_Float_operation},
5779 : : {"DecOverflow", MPD_Overflow},
5780 : : {"DecRounded", MPD_Rounded},
5781 : : {"DecSubnormal", MPD_Subnormal},
5782 : : {"DecUnderflow", MPD_Underflow},
5783 : : {"DecErrors", MPD_Errors},
5784 : : {"DecTraps", MPD_Traps},
5785 : : #endif
5786 : : {NULL}
5787 : : };
5788 : :
5789 : :
5790 : : #define CHECK_INT(expr) \
5791 : : do { if ((expr) < 0) goto error; } while (0)
5792 : : #define ASSIGN_PTR(result, expr) \
5793 : : do { result = (expr); if (result == NULL) goto error; } while (0)
5794 : : #define CHECK_PTR(expr) \
5795 : : do { if ((expr) == NULL) goto error; } while (0)
5796 : :
5797 : :
5798 : : static PyCFunction
5799 : 100 : cfunc_noargs(PyTypeObject *t, const char *name)
5800 : : {
5801 : : struct PyMethodDef *m;
5802 : :
5803 [ - + ]: 100 : if (t->tp_methods == NULL) {
5804 : 0 : goto error;
5805 : : }
5806 : :
5807 [ + - ]: 400 : for (m = t->tp_methods; m->ml_name != NULL; m++) {
5808 [ + + ]: 400 : if (strcmp(name, m->ml_name) == 0) {
5809 [ - + ]: 100 : if (!(m->ml_flags & METH_NOARGS)) {
5810 : 0 : goto error;
5811 : : }
5812 : 100 : return m->ml_meth;
5813 : : }
5814 : : }
5815 : :
5816 : 0 : error:
5817 : 0 : PyErr_Format(PyExc_RuntimeError,
5818 : : "internal error: could not find method %s", name);
5819 : 0 : return NULL;
5820 : : }
5821 : :
5822 : :
5823 : : PyMODINIT_FUNC
5824 : 50 : PyInit__decimal(void)
5825 : : {
5826 : 50 : PyObject *m = NULL;
5827 : 50 : PyObject *numbers = NULL;
5828 : 50 : PyObject *Number = NULL;
5829 : 50 : PyObject *collections = NULL;
5830 : 50 : PyObject *collections_abc = NULL;
5831 : 50 : PyObject *MutableMapping = NULL;
5832 : 50 : PyObject *obj = NULL;
5833 : : DecCondMap *cm;
5834 : : struct ssize_constmap *ssize_cm;
5835 : : struct int_constmap *int_cm;
5836 : : int i;
5837 : :
5838 : :
5839 : : /* Init libmpdec */
5840 : 50 : mpd_traphandler = dec_traphandler;
5841 : 50 : mpd_mallocfunc = PyMem_Malloc;
5842 : 50 : mpd_reallocfunc = PyMem_Realloc;
5843 : 50 : mpd_callocfunc = mpd_callocfunc_em;
5844 : 50 : mpd_free = PyMem_Free;
5845 : 50 : mpd_setminalloc(_Py_DEC_MINALLOC);
5846 : :
5847 : :
5848 : : /* Init external C-API functions */
5849 : 50 : _py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
5850 : 50 : _py_long_floor_divide = PyLong_Type.tp_as_number->nb_floor_divide;
5851 : 50 : _py_long_power = PyLong_Type.tp_as_number->nb_power;
5852 : 50 : _py_float_abs = PyFloat_Type.tp_as_number->nb_absolute;
5853 [ - + ]: 50 : ASSIGN_PTR(_py_float_as_integer_ratio, cfunc_noargs(&PyFloat_Type,
5854 : : "as_integer_ratio"));
5855 [ - + ]: 50 : ASSIGN_PTR(_py_long_bit_length, cfunc_noargs(&PyLong_Type, "bit_length"));
5856 : :
5857 : :
5858 : : /* Init types */
5859 : 50 : PyDec_Type.tp_base = &PyBaseObject_Type;
5860 : 50 : PyDecContext_Type.tp_base = &PyBaseObject_Type;
5861 : 50 : PyDecContextManager_Type.tp_base = &PyBaseObject_Type;
5862 : 50 : PyDecSignalDictMixin_Type.tp_base = &PyBaseObject_Type;
5863 : :
5864 [ - + ]: 50 : CHECK_INT(PyType_Ready(&PyDec_Type));
5865 [ - + ]: 50 : CHECK_INT(PyType_Ready(&PyDecContext_Type));
5866 [ - + ]: 50 : CHECK_INT(PyType_Ready(&PyDecSignalDictMixin_Type));
5867 [ - + ]: 50 : CHECK_INT(PyType_Ready(&PyDecContextManager_Type));
5868 : :
5869 [ - + ]: 50 : ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
5870 [ - + ]: 50 : CHECK_INT(PyDict_SetItemString(PyDec_Type.tp_dict, "__module__", obj));
5871 [ - + ]: 50 : CHECK_INT(PyDict_SetItemString(PyDecContext_Type.tp_dict,
5872 : : "__module__", obj));
5873 [ + - ]: 50 : Py_CLEAR(obj);
5874 : :
5875 : :
5876 : : /* Numeric abstract base classes */
5877 [ - + ]: 50 : ASSIGN_PTR(numbers, PyImport_ImportModule("numbers"));
5878 [ - + ]: 50 : ASSIGN_PTR(Number, PyObject_GetAttrString(numbers, "Number"));
5879 : : /* Register Decimal with the Number abstract base class */
5880 [ - + ]: 50 : ASSIGN_PTR(obj, PyObject_CallMethod(Number, "register", "(O)",
5881 : : (PyObject *)&PyDec_Type));
5882 [ + - ]: 50 : Py_CLEAR(obj);
5883 : : /* Rational is a global variable used for fraction comparisons. */
5884 [ - + ]: 50 : ASSIGN_PTR(Rational, PyObject_GetAttrString(numbers, "Rational"));
5885 : : /* Done with numbers, Number */
5886 [ + - ]: 50 : Py_CLEAR(numbers);
5887 [ + - ]: 50 : Py_CLEAR(Number);
5888 : :
5889 : : /* DecimalTuple */
5890 [ - + ]: 50 : ASSIGN_PTR(collections, PyImport_ImportModule("collections"));
5891 [ - + ]: 50 : ASSIGN_PTR(DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
5892 : : "namedtuple", "(ss)", "DecimalTuple",
5893 : : "sign digits exponent"));
5894 : :
5895 [ - + ]: 50 : ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
5896 [ - + ]: 50 : CHECK_INT(PyDict_SetItemString(DecimalTuple->tp_dict, "__module__", obj));
5897 [ + - ]: 50 : Py_CLEAR(obj);
5898 : :
5899 : : /* MutableMapping */
5900 [ - + ]: 50 : ASSIGN_PTR(collections_abc, PyImport_ImportModule("collections.abc"));
5901 [ - + ]: 50 : ASSIGN_PTR(MutableMapping, PyObject_GetAttrString(collections_abc,
5902 : : "MutableMapping"));
5903 : : /* Create SignalDict type */
5904 [ - + ]: 50 : ASSIGN_PTR(PyDecSignalDict_Type,
5905 : : (PyTypeObject *)PyObject_CallFunction(
5906 : : (PyObject *)&PyType_Type, "s(OO){}",
5907 : : "SignalDict", &PyDecSignalDictMixin_Type,
5908 : : MutableMapping));
5909 : :
5910 : : /* Done with collections, MutableMapping */
5911 [ + - ]: 50 : Py_CLEAR(collections);
5912 [ + - ]: 50 : Py_CLEAR(collections_abc);
5913 [ + - ]: 50 : Py_CLEAR(MutableMapping);
5914 : :
5915 : :
5916 : : /* Create the module */
5917 [ - + ]: 50 : ASSIGN_PTR(m, PyModule_Create(&_decimal_module));
5918 : :
5919 : :
5920 : : /* Add types to the module */
5921 : 50 : Py_INCREF(&PyDec_Type);
5922 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "Decimal", (PyObject *)&PyDec_Type));
5923 : 50 : Py_INCREF(&PyDecContext_Type);
5924 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "Context",
5925 : : (PyObject *)&PyDecContext_Type));
5926 : 50 : Py_INCREF(DecimalTuple);
5927 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "DecimalTuple", (PyObject *)DecimalTuple));
5928 : :
5929 : :
5930 : : /* Create top level exception */
5931 [ - + ]: 50 : ASSIGN_PTR(DecimalException, PyErr_NewException(
5932 : : "decimal.DecimalException",
5933 : : PyExc_ArithmeticError, NULL));
5934 : 50 : Py_INCREF(DecimalException);
5935 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "DecimalException", DecimalException));
5936 : :
5937 : : /* Create signal tuple */
5938 [ - + ]: 50 : ASSIGN_PTR(SignalTuple, PyTuple_New(SIGNAL_MAP_LEN));
5939 : :
5940 : : /* Add exceptions that correspond to IEEE signals */
5941 [ + + ]: 500 : for (i = SIGNAL_MAP_LEN-1; i >= 0; i--) {
5942 : : PyObject *base;
5943 : :
5944 : 450 : cm = signal_map + i;
5945 : :
5946 [ + + + + : 450 : switch (cm->flag) {
+ ]
5947 : 50 : case MPD_Float_operation:
5948 : 50 : base = PyTuple_Pack(2, DecimalException, PyExc_TypeError);
5949 : 50 : break;
5950 : 50 : case MPD_Division_by_zero:
5951 : 50 : base = PyTuple_Pack(2, DecimalException, PyExc_ZeroDivisionError);
5952 : 50 : break;
5953 : 50 : case MPD_Overflow:
5954 : 50 : base = PyTuple_Pack(2, signal_map[INEXACT].ex,
5955 : : signal_map[ROUNDED].ex);
5956 : 50 : break;
5957 : 50 : case MPD_Underflow:
5958 : 50 : base = PyTuple_Pack(3, signal_map[INEXACT].ex,
5959 : : signal_map[ROUNDED].ex,
5960 : : signal_map[SUBNORMAL].ex);
5961 : 50 : break;
5962 : 250 : default:
5963 : 250 : base = PyTuple_Pack(1, DecimalException);
5964 : 250 : break;
5965 : : }
5966 : :
5967 [ - + ]: 450 : if (base == NULL) {
5968 : 0 : goto error; /* GCOV_NOT_REACHED */
5969 : : }
5970 : :
5971 [ - + ]: 450 : ASSIGN_PTR(cm->ex, PyErr_NewException(cm->fqname, base, NULL));
5972 : 450 : Py_DECREF(base);
5973 : :
5974 : : /* add to module */
5975 : 450 : Py_INCREF(cm->ex);
5976 [ - + ]: 450 : CHECK_INT(PyModule_AddObject(m, cm->name, cm->ex));
5977 : :
5978 : : /* add to signal tuple */
5979 : 450 : Py_INCREF(cm->ex);
5980 : 450 : PyTuple_SET_ITEM(SignalTuple, i, cm->ex);
5981 : : }
5982 : :
5983 : : /*
5984 : : * Unfortunately, InvalidOperation is a signal that comprises
5985 : : * several conditions, including InvalidOperation! Naming the
5986 : : * signal IEEEInvalidOperation would prevent the confusion.
5987 : : */
5988 : 50 : cond_map[0].ex = signal_map[0].ex;
5989 : :
5990 : : /* Add remaining exceptions, inherit from InvalidOperation */
5991 [ + + ]: 250 : for (cm = cond_map+1; cm->name != NULL; cm++) {
5992 : : PyObject *base;
5993 [ + + ]: 200 : if (cm->flag == MPD_Division_undefined) {
5994 : 50 : base = PyTuple_Pack(2, signal_map[0].ex, PyExc_ZeroDivisionError);
5995 : : }
5996 : : else {
5997 : 150 : base = PyTuple_Pack(1, signal_map[0].ex);
5998 : : }
5999 [ - + ]: 200 : if (base == NULL) {
6000 : 0 : goto error; /* GCOV_NOT_REACHED */
6001 : : }
6002 : :
6003 [ - + ]: 200 : ASSIGN_PTR(cm->ex, PyErr_NewException(cm->fqname, base, NULL));
6004 : 200 : Py_DECREF(base);
6005 : :
6006 : 200 : Py_INCREF(cm->ex);
6007 [ - + ]: 200 : CHECK_INT(PyModule_AddObject(m, cm->name, cm->ex));
6008 : : }
6009 : :
6010 : :
6011 : : /* Init default context template first */
6012 [ - + ]: 50 : ASSIGN_PTR(default_context_template,
6013 : : PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
6014 : 50 : Py_INCREF(default_context_template);
6015 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "DefaultContext",
6016 : : default_context_template));
6017 : :
6018 : : #ifndef WITH_DECIMAL_CONTEXTVAR
6019 : : ASSIGN_PTR(tls_context_key, PyUnicode_FromString("___DECIMAL_CTX__"));
6020 : : Py_INCREF(Py_False);
6021 : : CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_False));
6022 : : #else
6023 [ - + ]: 50 : ASSIGN_PTR(current_context_var, PyContextVar_New("decimal_context", NULL));
6024 : 50 : Py_INCREF(Py_True);
6025 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "HAVE_CONTEXTVAR", Py_True));
6026 : : #endif
6027 : 50 : Py_INCREF(Py_True);
6028 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "HAVE_THREADS", Py_True));
6029 : :
6030 : : /* Init basic context template */
6031 [ - + ]: 50 : ASSIGN_PTR(basic_context_template,
6032 : : PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
6033 : 50 : init_basic_context(basic_context_template);
6034 : 50 : Py_INCREF(basic_context_template);
6035 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "BasicContext",
6036 : : basic_context_template));
6037 : :
6038 : : /* Init extended context template */
6039 [ - + ]: 50 : ASSIGN_PTR(extended_context_template,
6040 : : PyObject_CallObject((PyObject *)&PyDecContext_Type, NULL));
6041 : 50 : init_extended_context(extended_context_template);
6042 : 50 : Py_INCREF(extended_context_template);
6043 [ - + ]: 50 : CHECK_INT(PyModule_AddObject(m, "ExtendedContext",
6044 : : extended_context_template));
6045 : :
6046 : :
6047 : : /* Init mpd_ssize_t constants */
6048 [ + + ]: 250 : for (ssize_cm = ssize_constants; ssize_cm->name != NULL; ssize_cm++) {
6049 [ - + ]: 200 : ASSIGN_PTR(obj, PyLong_FromSsize_t(ssize_cm->val));
6050 [ - + ]: 200 : CHECK_INT(PyModule_AddObject(m, ssize_cm->name, obj));
6051 : 200 : obj = NULL;
6052 : : }
6053 : :
6054 : : /* Init int constants */
6055 [ - + ]: 50 : for (int_cm = int_constants; int_cm->name != NULL; int_cm++) {
6056 [ # # ]: 0 : CHECK_INT(PyModule_AddIntConstant(m, int_cm->name,
6057 : : int_cm->val));
6058 : : }
6059 : :
6060 : : /* Init string constants */
6061 [ + + ]: 450 : for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
6062 [ - + ]: 400 : ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
6063 : 400 : Py_INCREF(round_map[i]);
6064 [ - + ]: 400 : CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], round_map[i]));
6065 : : }
6066 : :
6067 : : /* Add specification version number */
6068 [ - + ]: 50 : CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
6069 [ - + ]: 50 : CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
6070 : :
6071 : :
6072 : 50 : return m;
6073 : :
6074 : :
6075 : 0 : error:
6076 [ # # ]: 0 : Py_CLEAR(obj); /* GCOV_NOT_REACHED */
6077 [ # # ]: 0 : Py_CLEAR(numbers); /* GCOV_NOT_REACHED */
6078 [ # # ]: 0 : Py_CLEAR(Number); /* GCOV_NOT_REACHED */
6079 [ # # ]: 0 : Py_CLEAR(Rational); /* GCOV_NOT_REACHED */
6080 [ # # ]: 0 : Py_CLEAR(collections); /* GCOV_NOT_REACHED */
6081 [ # # ]: 0 : Py_CLEAR(collections_abc); /* GCOV_NOT_REACHED */
6082 [ # # ]: 0 : Py_CLEAR(MutableMapping); /* GCOV_NOT_REACHED */
6083 [ # # ]: 0 : Py_CLEAR(SignalTuple); /* GCOV_NOT_REACHED */
6084 [ # # ]: 0 : Py_CLEAR(DecimalTuple); /* GCOV_NOT_REACHED */
6085 [ # # ]: 0 : Py_CLEAR(default_context_template); /* GCOV_NOT_REACHED */
6086 : : #ifndef WITH_DECIMAL_CONTEXTVAR
6087 : : Py_CLEAR(tls_context_key); /* GCOV_NOT_REACHED */
6088 : : #else
6089 [ # # ]: 0 : Py_CLEAR(current_context_var); /* GCOV_NOT_REACHED */
6090 : : #endif
6091 [ # # ]: 0 : Py_CLEAR(basic_context_template); /* GCOV_NOT_REACHED */
6092 [ # # ]: 0 : Py_CLEAR(extended_context_template); /* GCOV_NOT_REACHED */
6093 [ # # ]: 0 : Py_CLEAR(m); /* GCOV_NOT_REACHED */
6094 : :
6095 : 0 : return NULL; /* GCOV_NOT_REACHED */
6096 : : }
|