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