/ src / gmpy2_cache.c
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