gmpy2_cache.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_cache.c * 3 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 4 * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision * 5 * libraries. * 6 * * 7 * Copyright 2000 - 2009 Alex Martelli * 8 * * 9 * Copyright 2008 - 2021 Case Van Horsen * 10 * * 11 * This file is part of GMPY2. * 12 * * 13 * GMPY2 is free software: you can redistribute it and/or modify it under * 14 * the terms of the GNU Lesser General Public License as published by the * 15 * Free Software Foundation, either version 3 of the License, or (at your * 16 * option) any later version. * 17 * * 18 * GMPY2 is distributed in the hope that it will be useful, but WITHOUT * 19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 21 * License for more details. * 22 * * 23 * You should have received a copy of the GNU Lesser General Public * 24 * License along with GMPY2; if not, see <http://www.gnu.org/licenses/> * 25 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 26 27 28 /* gmpy2 caches objects so they can be reused quickly without involving a new 29 * memory allocation or object construction. 30 * 31 * The "py???cache" is used to cache Py??? objects. The cache is accessed 32 * via Py???_new/Py???_dealloc. The functions set_py???cache and 33 * set_py???cache are used to change the size of the array used to the store 34 * the cached objects. 35 */ 36 37 /* Caching logic for Pympz. */ 38 39 static void 40 set_gmpympzcache(void) 41 { 42 if (global.in_gmpympzcache > global.cache_size) { 43 int i; 44 for (i = global.cache_size; i < global.in_gmpympzcache; ++i) { 45 mpz_clear(global.gmpympzcache[i]->z); 46 PyObject_Del(global.gmpympzcache[i]); 47 } 48 global.in_gmpympzcache = global.cache_size; 49 } 50 global.gmpympzcache = realloc(global.gmpympzcache, sizeof(MPZ_Object)*global.cache_size); 51 } 52 53 /* GMPy_MPZ_New returns a reference to a new MPZ_Object. Its value 54 * is initialized to 0. 55 */ 56 57 static MPZ_Object * 58 GMPy_MPZ_New(CTXT_Object *context) 59 { 60 MPZ_Object *result = NULL; 61 62 if (global.in_gmpympzcache) { 63 result = global.gmpympzcache[--(global.in_gmpympzcache)]; 64 /* Py_INCREF does not set the debugging pointers, so need to use 65 * _Py_NewReference instead. */ 66 _Py_NewReference((PyObject*)result); 67 mpz_set_ui(result->z, 0); 68 result->hash_cache = -1; 69 } 70 else { 71 if ((result = PyObject_New(MPZ_Object, &MPZ_Type))) { 72 mpz_init(result->z); 73 result->hash_cache = -1; 74 } 75 } 76 return result; 77 } 78 79 /* GMPy_MPZ_NewInit returns a reference to an initialized MPZ_Object. It is 80 * used by mpz.__new__ to replace the old mpz() factory function. 81 */ 82 83 static PyObject * 84 GMPy_MPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds) 85 { 86 MPZ_Object *result = NULL; 87 PyObject *n = NULL; 88 PyObject *temp = NULL; 89 PyObject *out = NULL; 90 int base = 0; 91 Py_ssize_t argc; 92 static char *kwlist[] = {"s", "base", NULL }; 93 CTXT_Object *context = NULL; 94 95 if (type != &MPZ_Type) { 96 TYPE_ERROR("mpz.__new__() requires mpz type"); 97 return NULL; 98 } 99 100 /* Optimize the most common use cases first; either 0 or 1 argument */ 101 102 argc = PyTuple_GET_SIZE(args); 103 104 if (argc == 0) { 105 return (PyObject*)GMPy_MPZ_New(context); 106 } 107 108 if (argc == 1 && !keywds) { 109 n = PyTuple_GET_ITEM(args, 0); 110 111 if (MPZ_Check(n)) { 112 Py_INCREF(n); 113 return n; 114 } 115 116 if (PyIntOrLong_Check(n)) { 117 return (PyObject*)GMPy_MPZ_From_PyIntOrLong(n, context); 118 } 119 120 if (MPQ_Check(n)) { 121 return (PyObject*)GMPy_MPZ_From_MPQ((MPQ_Object*)n, context); 122 } 123 124 if (MPFR_Check(n)) { 125 return (PyObject*)GMPy_MPZ_From_MPFR((MPFR_Object*)n, context); 126 } 127 128 if (PyFloat_Check(n)) { 129 return (PyObject*)GMPy_MPZ_From_PyFloat(n, context); 130 } 131 132 if (XMPZ_Check(n)) { 133 return (PyObject*)GMPy_MPZ_From_XMPZ((XMPZ_Object*)n, context); 134 } 135 136 if (IS_FRACTION(n)) { 137 MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context); 138 139 if (temp) { 140 result = GMPy_MPZ_From_MPQ(temp, context); 141 Py_DECREF((PyObject*)temp); 142 } 143 return (PyObject*)result; 144 } 145 146 if (PyStrOrUnicode_Check(n)) { 147 return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context); 148 } 149 150 if (HAS_MPZ_CONVERSION(n)) { 151 out = (PyObject *) PyObject_CallMethod(n, "__mpz__", NULL); 152 153 if (out == NULL) 154 return out; 155 if (!MPZ_Check(out)) { 156 PyErr_Format(PyExc_TypeError, 157 "object of type '%.200s' can not be interpreted as mpz", 158 out->ob_type->tp_name); 159 Py_DECREF(out); 160 return NULL; 161 } 162 return out; 163 } 164 165 /* Try converting to integer. */ 166 temp = PyNumber_Long(n); 167 if (temp) { 168 result = GMPy_MPZ_From_PyIntOrLong(temp, context); 169 Py_DECREF(temp); 170 return (PyObject*)result; 171 } 172 173 TYPE_ERROR("mpz() requires numeric or string argument"); 174 return NULL; 175 } 176 177 if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) { 178 return NULL; 179 } 180 181 if ((base != 0) && ((base < 2)|| (base > 62))) { 182 VALUE_ERROR("base for mpz() must be 0 or in the interval [2, 62]"); 183 return NULL; 184 } 185 186 if (PyStrOrUnicode_Check(n)) { 187 return (PyObject*)GMPy_MPZ_From_PyStr(n, base, context); 188 } 189 190 if (IS_REAL(n)) { 191 TYPE_ERROR("mpz() with number argument only takes 1 argument"); 192 } 193 else { 194 TYPE_ERROR("mpz() requires numeric or string (and optional base) arguments"); 195 } 196 return NULL; 197 } 198 199 static void 200 GMPy_MPZ_Dealloc(MPZ_Object *self) 201 { 202 if (global.in_gmpympzcache < global.cache_size && 203 self->z->_mp_alloc <= global.cache_obsize) { 204 global.gmpympzcache[(global.in_gmpympzcache)++] = self; 205 } 206 else { 207 mpz_clear(self->z); 208 PyObject_Del(self); 209 } 210 } 211 212 /* Caching logic for Pyxmpz. */ 213 214 static void 215 set_gmpyxmpzcache(void) 216 { 217 if (global.in_gmpyxmpzcache > global.cache_size) { 218 int i; 219 for (i = global.cache_size; i < global.in_gmpyxmpzcache; ++i) { 220 mpz_clear(global.gmpyxmpzcache[i]->z); 221 PyObject_Del(global.gmpyxmpzcache[i]); 222 } 223 global.in_gmpyxmpzcache = global.cache_size; 224 } 225 global.gmpyxmpzcache = realloc(global.gmpyxmpzcache, sizeof(XMPZ_Object)*global.cache_size); 226 } 227 228 static XMPZ_Object * 229 GMPy_XMPZ_New(CTXT_Object *context) 230 { 231 XMPZ_Object *result = NULL; 232 233 if (global.in_gmpyxmpzcache) { 234 result = global.gmpyxmpzcache[--(global.in_gmpyxmpzcache)]; 235 /* Py_INCREF does not set the debugging pointers, so need to use 236 * _Py_NewReference instead. */ 237 _Py_NewReference((PyObject*)result); 238 mpz_set_ui(result->z, 0); 239 } 240 else { 241 if ((result = PyObject_New(XMPZ_Object, &XMPZ_Type))) { 242 mpz_init(result->z); 243 } 244 } 245 return result; 246 } 247 248 static PyObject * 249 GMPy_XMPZ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds) 250 { 251 XMPZ_Object *result = NULL; 252 PyObject *n = NULL; 253 PyObject *temp = NULL; 254 int base = 0; 255 Py_ssize_t argc; 256 static char *kwlist[] = {"s", "base", NULL }; 257 CTXT_Object *context = NULL; 258 259 if (type != &XMPZ_Type) { 260 TYPE_ERROR("xmpz.__new__() requires xmpz type"); 261 return NULL; 262 } 263 264 /* Optimize the most common use cases first; either 0 or 1 argument */ 265 266 argc = PyTuple_GET_SIZE(args); 267 268 if (argc == 0) { 269 return (PyObject*)GMPy_XMPZ_New(context); 270 } 271 272 if (argc == 1 && !keywds) { 273 n = PyTuple_GET_ITEM(args, 0); 274 275 if (XMPZ_Check(n)) { 276 Py_INCREF(n); 277 return n; 278 } 279 280 if (PyIntOrLong_Check(n)) { 281 return (PyObject*)GMPy_XMPZ_From_PyIntOrLong(n, context); 282 } 283 284 if (MPQ_Check(n)) { 285 return (PyObject*)GMPy_XMPZ_From_MPQ((MPQ_Object*)n, context); 286 } 287 288 if (MPFR_Check(n)) { 289 return (PyObject*)GMPy_XMPZ_From_MPFR((MPFR_Object*)n, context); 290 } 291 292 if (PyFloat_Check(n)) { 293 return (PyObject*)GMPy_XMPZ_From_PyFloat(n, context); 294 } 295 296 if (MPZ_Check(n)) { 297 return (PyObject*)GMPy_XMPZ_From_MPZ((MPZ_Object*)n, context); 298 } 299 300 if (IS_FRACTION(n)) { 301 MPQ_Object *temp = GMPy_MPQ_From_Fraction(n, context); 302 303 if (temp) { 304 result = GMPy_XMPZ_From_MPQ(temp, context); 305 Py_DECREF((PyObject*)temp); 306 } 307 return (PyObject*)result; 308 } 309 310 if (PyStrOrUnicode_Check(n)) { 311 return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context); 312 } 313 314 /* Try converting to integer. */ 315 temp = PyNumber_Long(n); 316 if (temp) { 317 result = GMPy_XMPZ_From_PyIntOrLong(temp, context); 318 Py_DECREF(temp); 319 return (PyObject*)result; 320 } 321 322 TYPE_ERROR("xmpz() requires numeric or string argument"); 323 return NULL; 324 } 325 326 if (!PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) { 327 return NULL; 328 } 329 330 if ((base != 0) && ((base < 2)|| (base > 62))) { 331 VALUE_ERROR("base for xmpz() must be 0 or in the interval [2, 62]"); 332 return NULL; 333 } 334 335 if (PyStrOrUnicode_Check(n)) { 336 return (PyObject*)GMPy_XMPZ_From_PyStr(n, base, context); 337 } 338 339 if (IS_REAL(n)) { 340 TYPE_ERROR("xmpz() with number argument only takes 1 argument"); 341 } 342 else { 343 TYPE_ERROR("xmpz() requires numeric or string (and optional base) arguments"); 344 } 345 return NULL; 346 } 347 348 static void 349 GMPy_XMPZ_Dealloc(XMPZ_Object *obj) 350 { 351 if (global.in_gmpyxmpzcache < global.cache_size && 352 obj->z->_mp_alloc <= global.cache_obsize) { 353 global.gmpyxmpzcache[(global.in_gmpyxmpzcache)++] = obj; 354 } 355 else { 356 mpz_clear(obj->z); 357 PyObject_Del((PyObject*)obj); 358 } 359 } 360 361 /* Caching logic for Pympq. */ 362 363 static void 364 set_gmpympqcache(void) 365 { 366 if (global.in_gmpympqcache > global.cache_size) { 367 int i; 368 for (i = global.cache_size; i < global.in_gmpympqcache; ++i) { 369 mpq_clear(global.gmpympqcache[i]->q); 370 PyObject_Del(global.gmpympqcache[i]); 371 } 372 global.in_gmpympqcache = global.cache_size; 373 } 374 global.gmpympqcache = realloc(global.gmpympqcache, sizeof(MPQ_Object)*global.cache_size); 375 } 376 377 static MPQ_Object * 378 GMPy_MPQ_New(CTXT_Object *context) 379 { 380 MPQ_Object *result = NULL; 381 382 if (global.in_gmpympqcache) { 383 result = global.gmpympqcache[--(global.in_gmpympqcache)]; 384 /* Py_INCREF does not set the debugging pointers, so need to use 385 _Py_NewReference instead. */ 386 _Py_NewReference((PyObject*)result); 387 } 388 else { 389 if (!(result = PyObject_New(MPQ_Object, &MPQ_Type))) { 390 /* LCOV_EXCL_START */ 391 return NULL; 392 /* LCOV_EXCL_STOP */ 393 } 394 mpq_init(result->q); 395 } 396 result->hash_cache = -1; 397 return result; 398 } 399 400 static PyObject * 401 GMPy_MPQ_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds) 402 { 403 MPQ_Object *result = NULL, *temp = NULL; 404 PyObject *n = NULL, *m = NULL; 405 int base = 10; 406 Py_ssize_t argc, keywdc = 0; 407 static char *kwlist[] = {"s", "base", NULL }; 408 CTXT_Object *context = NULL; 409 410 if (type != &MPQ_Type) { 411 TYPE_ERROR("mpq.__new__() requires mpq type"); 412 return NULL; 413 } 414 415 argc = PyTuple_Size(args); 416 if (keywds) { 417 keywdc = PyDict_Size(keywds); 418 } 419 420 if (argc + keywdc > 2) { 421 TYPE_ERROR("mpq() takes at most 2 arguments"); 422 return NULL; 423 } 424 425 if (argc + keywdc == 0) { 426 if ((result = GMPy_MPQ_New(context))) { 427 mpq_set_ui(result->q, 0, 1); 428 } 429 return (PyObject*)result; 430 } 431 432 if (argc == 0) { 433 TYPE_ERROR("mpq() requires at least one non-keyword argument"); 434 return NULL; 435 } 436 437 n = PyTuple_GetItem(args, 0); 438 439 /* Handle the case where the first argument is a string. */ 440 if (PyStrOrUnicode_Check(n)) { 441 /* keyword base is legal */ 442 if (keywdc || argc > 1) { 443 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base))) { 444 return NULL; 445 } 446 } 447 448 if ((base != 0) && ((base < 2) || (base > 62))) { 449 VALUE_ERROR("base for mpq() must be 0 or in the interval [2, 62]"); 450 return NULL; 451 } 452 453 return (PyObject*)GMPy_MPQ_From_PyStr(n, base, context); 454 } 455 456 /* Handle 1 argument. It must be non-complex number or an object with a __mpq__ method. */ 457 if (argc == 1) { 458 if (IS_REAL(n)) { 459 return (PyObject *) GMPy_MPQ_From_Number(n, context); 460 } 461 } 462 463 /* Handle 2 arguments. Both arguments must be integer or rational. */ 464 if (argc == 2) { 465 m = PyTuple_GetItem(args, 1); 466 467 if (IS_RATIONAL(n) && IS_RATIONAL(m)) { 468 result = GMPy_MPQ_From_Rational(n, context); 469 temp = GMPy_MPQ_From_Rational(m, context); 470 if (!result || !temp) { 471 Py_XDECREF((PyObject*)result); 472 Py_XDECREF((PyObject*)temp); 473 return NULL; 474 } 475 476 if (mpq_sgn(temp->q) == 0) { 477 ZERO_ERROR("zero denominator in mpq()"); 478 Py_DECREF((PyObject*)result); 479 Py_DECREF((PyObject*)temp); 480 return NULL; 481 } 482 483 mpq_div(result->q, result->q, temp->q); 484 Py_DECREF((PyObject*)temp); 485 return (PyObject*)result; 486 } 487 } 488 489 TYPE_ERROR("mpq() requires numeric or string argument"); 490 return NULL; 491 } 492 493 static void 494 GMPy_MPQ_Dealloc(MPQ_Object *self) 495 { 496 if (global.in_gmpympqcache<global.cache_size && 497 mpq_numref(self->q)->_mp_alloc <= global.cache_obsize && 498 mpq_denref(self->q)->_mp_alloc <= global.cache_obsize) { 499 global.gmpympqcache[(global.in_gmpympqcache)++] = self; 500 } 501 else { 502 mpq_clear(self->q); 503 PyObject_Del(self); 504 } 505 } 506 507 /* Caching logic for Pympfr. */ 508 509 static void 510 set_gmpympfrcache(void) 511 { 512 if (global.in_gmpympfrcache > global.cache_size) { 513 int i; 514 for (i = global.cache_size; i < global.in_gmpympfrcache; ++i) { 515 mpfr_clear(global.gmpympfrcache[i]->f); 516 PyObject_Del(global.gmpympfrcache[i]); 517 } 518 global.in_gmpympfrcache = global.cache_size; 519 } 520 global.gmpympfrcache = realloc(global.gmpympfrcache, sizeof(MPFR_Object)*global.cache_size); 521 } 522 523 static MPFR_Object * 524 GMPy_MPFR_New(mpfr_prec_t bits, CTXT_Object *context) 525 { 526 MPFR_Object *result; 527 528 if (bits < 2) { 529 CHECK_CONTEXT(context); 530 bits = GET_MPFR_PREC(context); 531 } 532 533 if (bits < MPFR_PREC_MIN || bits > MPFR_PREC_MAX) { 534 VALUE_ERROR("invalid value for precision"); 535 return NULL; 536 } 537 538 if (global.in_gmpympfrcache) { 539 result = global.gmpympfrcache[--(global.in_gmpympfrcache)]; 540 /* Py_INCREF does not set the debugging pointers, so need to use 541 _Py_NewReference instead. */ 542 _Py_NewReference((PyObject*)result); 543 mpfr_set_prec(result->f, bits); 544 } 545 else { 546 if (!(result = PyObject_New(MPFR_Object, &MPFR_Type))) { 547 /* LCOV_EXCL_START */ 548 return NULL; 549 /* LCOV_EXCL_STOP */ 550 } 551 mpfr_init2(result->f, bits); 552 } 553 result->hash_cache = -1; 554 result->rc = 0; 555 return result; 556 } 557 558 static PyObject * 559 GMPy_MPFR_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds) 560 { 561 MPFR_Object *result = NULL; 562 CTXT_Object *context = NULL; 563 Py_ssize_t argc, keywdc = 0; 564 PyObject *arg0 = NULL; 565 PyObject *out = NULL; 566 int base = 0; 567 568 569 /* Assumes mpfr_prec_t is the same as a long. */ 570 mpfr_prec_t prec = 0; 571 572 static char *kwlist_s[] = {"s", "precision", "base", "context", NULL}; 573 static char *kwlist_n[] = {"n", "precision", "context", NULL}; 574 575 if (type != &MPFR_Type) { 576 TYPE_ERROR("mpfr.__new__() requires mpfr type"); 577 return NULL; 578 } 579 580 CHECK_CONTEXT(context); 581 582 argc = PyTuple_Size(args); 583 if (keywds) { 584 keywdc = PyDict_Size(keywds); 585 } 586 587 if (argc + keywdc > 4) { 588 TYPE_ERROR("mpfr() takes at most 4 arguments"); 589 return NULL; 590 } 591 592 if (argc + keywdc == 0) { 593 if ((result = GMPy_MPFR_New(0, context))) { 594 mpfr_set_ui(result->f, 0, MPFR_RNDN); 595 } 596 return (PyObject*)result; 597 } 598 599 if (argc == 0) { 600 TYPE_ERROR("mpfr() requires at least one non-keyword argument"); 601 return NULL; 602 } 603 604 arg0 = PyTuple_GET_ITEM(args, 0); 605 606 /* A string can have precision, base, and context as additional arguments. */ 607 if (PyStrOrUnicode_Check(arg0)) { 608 if (keywdc || argc > 1) { 609 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|liO", kwlist_s, 610 &arg0, &prec, &base, &context))) 611 return NULL; 612 } 613 614 if (!CTXT_Check(context)) { 615 TYPE_ERROR("context argument is not a valid context"); 616 return NULL; 617 } 618 619 if (prec < 0) { 620 VALUE_ERROR("precision for mpfr() must be >= 0"); 621 return NULL; 622 } 623 624 if (base != 0 && (base < 2 || base > 62)) { 625 VALUE_ERROR("base for mpfr() must be 0 or in the interval [2, 62]"); 626 return NULL; 627 } 628 629 return (PyObject*)GMPy_MPFR_From_PyStr(arg0, base, prec, context); 630 } 631 632 if (HAS_MPFR_CONVERSION(arg0)) { 633 out = (PyObject *) PyObject_CallMethod(arg0, "__mpfr__", NULL); 634 635 if(out == NULL) 636 return out; 637 if (!MPFR_Check(out)) { 638 PyErr_Format(PyExc_TypeError, 639 "object of type '%.200s' can not be interpreted as mpfr", 640 out->ob_type->tp_name); 641 Py_DECREF(out); 642 return NULL; 643 } 644 return out; 645 } 646 647 /* A number can only have precision and context as additional arguments. */ 648 if (IS_REAL(arg0)) { 649 if (keywdc || argc > 1) { 650 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|lO", kwlist_n, 651 &arg0, &prec, &context))) 652 return NULL; 653 } 654 655 if (!CTXT_Check(context)) { 656 TYPE_ERROR("context argument is not a valid context"); 657 return NULL; 658 } 659 660 if (prec < 0) { 661 VALUE_ERROR("precision for mpfr() must be >= 0"); 662 return NULL; 663 } 664 665 return (PyObject*)GMPy_MPFR_From_Real(arg0, prec, context); 666 } 667 668 TYPE_ERROR("mpfr() requires numeric or string argument"); 669 return NULL; 670 } 671 672 static void 673 GMPy_MPFR_Dealloc(MPFR_Object *self) 674 { 675 size_t msize; 676 677 /* Calculate the number of limbs in the mantissa. */ 678 msize = (self->f->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; 679 if (global.in_gmpympfrcache < global.cache_size && 680 msize <= (size_t)global.cache_obsize) { 681 global.gmpympfrcache[(global.in_gmpympfrcache)++] = self; 682 } 683 else { 684 mpfr_clear(self->f); 685 PyObject_Del(self); 686 } 687 } 688 689 static void 690 set_gmpympccache(void) 691 { 692 if (global.in_gmpympccache > global.cache_size) { 693 int i; 694 for (i = global.cache_size; i < global.in_gmpympccache; ++i) { 695 mpc_clear(global.gmpympccache[i]->c); 696 PyObject_Del(global.gmpympccache[i]); 697 } 698 global.in_gmpympccache = global.cache_size; 699 } 700 global.gmpympccache = realloc(global.gmpympccache, sizeof(MPC_Object)*global.cache_size); 701 } 702 703 704 static MPC_Object * 705 GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context) 706 { 707 MPC_Object *self; 708 709 if (rprec < 2) { 710 CHECK_CONTEXT(context); 711 rprec = GET_REAL_PREC(context); 712 } 713 714 if (iprec < 2) { 715 CHECK_CONTEXT(context); 716 iprec = GET_IMAG_PREC(context); 717 } 718 719 if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX || 720 iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) { 721 VALUE_ERROR("invalid value for precision"); 722 return NULL; 723 } 724 if (global.in_gmpympccache) { 725 self = global.gmpympccache[--(global.in_gmpympccache)]; 726 /* Py_INCREF does not set the debugging pointers, so need to use 727 _Py_NewReference instead. */ 728 _Py_NewReference((PyObject*)self); 729 if (rprec == iprec) { 730 mpc_set_prec(self->c, rprec); 731 } 732 else { 733 mpc_clear(self->c); 734 mpc_init3(self->c, rprec, iprec); 735 } 736 } 737 else { 738 if (!(self = PyObject_New(MPC_Object, &MPC_Type))) { 739 /* LCOV_EXCL_START */ 740 return NULL; 741 /* LCOV_EXCL_STOP */ 742 } 743 mpc_init3(self->c, rprec, iprec); 744 } 745 self->hash_cache = -1; 746 self->rc = 0; 747 return self; 748 } 749 750 static PyObject * 751 GMPy_MPC_NewInit(PyTypeObject *type, PyObject *args, PyObject *keywds) 752 { 753 MPC_Object *result = NULL; 754 MPFR_Object *tempreal = NULL, *tempimag = NULL; 755 PyObject *arg0 = NULL, *arg1 = NULL, *prec = NULL, *out = NULL; 756 int base = 10; 757 Py_ssize_t argc = 0, keywdc = 0; 758 CTXT_Object *context = NULL; 759 760 /* Assumes mpfr_prec_t is the same as a long. */ 761 mpfr_prec_t rprec = 0, iprec = 0; 762 763 static char *kwlist_c[] = {"c", "precision", "context", NULL}; 764 static char *kwlist_r[] = {"real", "imag", "precision", "context", NULL}; 765 static char *kwlist_s[] = {"s", "precision", "base", "context", NULL}; 766 767 if (type != &MPC_Type) { 768 TYPE_ERROR("mpc.__new__() requires mpc type"); 769 return NULL; 770 } 771 772 CHECK_CONTEXT(context); 773 774 argc = PyTuple_Size(args); 775 if (keywds) { 776 keywdc = PyDict_Size(keywds); 777 } 778 779 if (argc + keywdc > 4) { 780 TYPE_ERROR("mpc() takes at most 4 arguments"); 781 return NULL; 782 } 783 784 if (argc + keywdc == 0) { 785 if ((result = GMPy_MPC_New(0, 0, context))) { 786 mpc_set_ui(result->c, 0, GET_MPC_ROUND(context)); 787 } 788 return (PyObject*)result; 789 } 790 791 if (argc == 0) { 792 TYPE_ERROR("mpc() requires at least one non-keyword argument"); 793 return NULL; 794 } 795 796 arg0 = PyTuple_GET_ITEM(args, 0); 797 798 /* A string can have precision, base, and context as additional arguments. 799 */ 800 801 if (PyStrOrUnicode_Check(arg0)) { 802 if (keywdc || argc > 1) { 803 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OiO", kwlist_s, 804 &arg0, &prec, &base, &context))) 805 return NULL; 806 } 807 808 if (!CTXT_Check(context)) { 809 TYPE_ERROR("context argument is not a valid context"); 810 return NULL; 811 } 812 813 if (prec) { 814 if (PyIntOrLong_Check(prec)) { 815 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec); 816 iprec = rprec; 817 } 818 else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { 819 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0)); 820 iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1)); 821 } 822 else { 823 TYPE_ERROR("precision for mpc() must be integer or tuple"); 824 return NULL; 825 } 826 827 if (rprec < 0 || iprec < 0) { 828 if (PyErr_Occurred()) { 829 VALUE_ERROR("invalid value for precision in mpc()"); 830 } 831 else { 832 VALUE_ERROR("precision for mpc() must be >= 0"); 833 } 834 return NULL; 835 } 836 } 837 838 if (base < 2 || base > 36) { 839 VALUE_ERROR("base for mpc() must be in the interval [2,36]"); 840 return NULL; 841 } 842 843 return (PyObject*)GMPy_MPC_From_PyStr(arg0, base, rprec, iprec, context); 844 } 845 846 if (HAS_MPC_CONVERSION(arg0)) { 847 out = (PyObject*) PyObject_CallMethod(arg0, "__mpc__", NULL); 848 if(out == NULL) 849 return out; 850 if (!MPC_Check(out)) { 851 PyErr_Format(PyExc_TypeError, 852 "object of type '%.200s' can not be interpreted as mpc", 853 out->ob_type->tp_name); 854 Py_DECREF(out); 855 return NULL; 856 } 857 return out; 858 } 859 860 /* Should special case PyFLoat to avoid double rounding. */ 861 862 if (IS_REAL(arg0)) { 863 if (keywdc || argc > 1) { 864 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|OOO", kwlist_r, 865 &arg0, &arg1, &prec, &context))) 866 return NULL; 867 } 868 869 if (!CTXT_Check(context)) { 870 TYPE_ERROR("context argument is not a valid context"); 871 return NULL; 872 } 873 874 if (prec) { 875 if (PyIntOrLong_Check(prec)) { 876 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec); 877 iprec = rprec; 878 } 879 else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { 880 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0)); 881 iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1)); 882 } 883 else { 884 TYPE_ERROR("precision for mpc() must be integer or tuple"); 885 return NULL; 886 } 887 888 if (rprec < 0 || iprec < 0) { 889 if (PyErr_Occurred()) { 890 VALUE_ERROR("invalid value for precision in mpc()"); 891 } 892 else { 893 VALUE_ERROR("precision for mpc() must be >= 0"); 894 } 895 return NULL; 896 } 897 } 898 899 if (arg1 && !IS_REAL(arg1)) { 900 TYPE_ERROR("invalid type for imaginary component in mpc()"); 901 return NULL; 902 } 903 904 tempreal = GMPy_MPFR_From_Real(arg0, rprec, context); 905 if (arg1) { 906 tempimag = GMPy_MPFR_From_Real(arg1, iprec, context); 907 } 908 else { 909 if ((tempimag = GMPy_MPFR_New(iprec, context))) { 910 mpfr_set_ui(tempimag->f, 0, MPFR_RNDN); 911 } 912 } 913 914 result = GMPy_MPC_New(rprec, iprec, context); 915 if (!tempreal || !tempimag || !result) { 916 Py_XDECREF(tempreal); 917 Py_XDECREF(tempimag); 918 Py_XDECREF(result); 919 TYPE_ERROR("mpc() requires string or numeric argument."); 920 return NULL; 921 } 922 923 mpc_set_fr_fr(result->c, tempreal->f, tempimag->f, GET_MPC_ROUND(context)); 924 Py_DECREF(tempreal); 925 Py_DECREF(tempimag); 926 return (PyObject*)result; 927 } 928 929 if (IS_COMPLEX_ONLY(arg0)) { 930 if (keywdc || argc > 1) { 931 if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|O", kwlist_c, 932 &arg0, &prec))) 933 return NULL; 934 } 935 936 if (prec) { 937 if (PyIntOrLong_Check(prec)) { 938 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(prec); 939 iprec = rprec; 940 } 941 else if (PyTuple_Check(prec) && PyTuple_Size(prec) == 2) { 942 rprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 0)); 943 iprec = (mpfr_prec_t)PyIntOrLong_AsLong(PyTuple_GET_ITEM(prec, 1)); 944 } 945 else { 946 TYPE_ERROR("precision for mpc() must be integer or tuple"); 947 return NULL; 948 } 949 950 if (rprec < 0 || iprec < 0) { 951 if (PyErr_Occurred()) { 952 VALUE_ERROR("invalid value for precision in mpc()"); 953 } 954 else { 955 VALUE_ERROR("precision for mpc() must be >= 0"); 956 } 957 return NULL; 958 } 959 } 960 961 if (PyComplex_Check(arg0)) { 962 result = GMPy_MPC_From_PyComplex(arg0, rprec, iprec, context); 963 } 964 else { 965 result = GMPy_MPC_From_MPC((MPC_Object*)arg0, rprec, iprec, context); 966 } 967 return (PyObject*)result; 968 } 969 970 TYPE_ERROR("mpc() requires numeric or string argument"); 971 return NULL; 972 } 973 974 static void 975 GMPy_MPC_Dealloc(MPC_Object *self) 976 { 977 size_t msize; 978 979 /* Calculate the number of limbs in the mantissa. */ 980 msize = (mpc_realref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; 981 msize += (mpc_imagref(self->c)->_mpfr_prec + mp_bits_per_limb - 1) / mp_bits_per_limb; 982 if (global.in_gmpympccache < global.cache_size && 983 msize <= (size_t)global.cache_obsize) { 984 global.gmpympccache[(global.in_gmpympccache)++] = self; 985 } 986 else { 987 mpc_clear(self->c); 988 PyObject_Del(self); 989 } 990 } 991