1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * gmpy2_convert_gmp.c                                                     *
3  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4  * Python interface to the GMP or MPIR, MPFR, and MPC multiple precision   *
5  * libraries.                                                              *
6  *                                                                         *
7  * Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,               *
8  *           2008, 2009 Alex Martelli                                      *
9  *                                                                         *
10  * Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014,                     *
11  *           2015, 2016, 2017, 2018, 2019, 2020 Case Van Horsen            *
12  *                                                                         *
13  * This file is part of GMPY2.                                             *
14  *                                                                         *
15  * GMPY2 is free software: you can redistribute it and/or modify it under  *
16  * the terms of the GNU Lesser General Public License as published by the  *
17  * Free Software Foundation, either version 3 of the License, or (at your  *
18  * option) any later version.                                              *
19  *                                                                         *
20  * GMPY2 is distributed in the hope that it will be useful, but WITHOUT    *
21  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or   *
22  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public    *
23  * License for more details.                                               *
24  *                                                                         *
25  * You should have received a copy of the GNU Lesser General Public        *
26  * License along with GMPY2; if not, see <http://www.gnu.org/licenses/>    *
27  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
28 
29 /* This file contains all the conversion functions for GMP data types.
30  *
31  * Overview
32  * --------
33  * gmpy2 tries to optimize the performance and accuracy of conversions from
34  * other numeric types. gmpy2 uses a LBYL (Look Before You Leap) approach and
35  * identifies the numeric type before conversion before conversion to a gmpy2
36  * type. The basic operations (+, -, *, /) are optimized to directly work with
37  * some basic types such as C longs or doubles.
38  */
39 
40 /* ======================================================================== *
41  * Conversion between native Python objects and MPZ.                        *
42  * ======================================================================== */
43 
44 static MPZ_Object *
GMPy_MPZ_From_PyIntOrLong(PyObject * obj,CTXT_Object * context)45 GMPy_MPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
46 {
47     MPZ_Object *result;
48     int negative;
49     Py_ssize_t len;
50     PyLongObject *templong = (PyLongObject*)obj;
51 
52     assert(PyIntOrLong_Check(obj));
53 
54     if(!(result = GMPy_MPZ_New(context))) {
55         /* LCOV_EXCL_START */
56         return NULL;
57         /* LCOV_EXCL_STOP */
58     }
59 
60 #ifdef PY2
61     if (PyInt_Check(obj)) {
62         mpz_set_si(result->z, PyInt_AS_LONG(obj));
63         return result;
64     }
65 #endif
66 
67     switch (Py_SIZE(templong)) {
68     case -1:
69         mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]);
70         break;
71     case 0:
72         mpz_set_si(result->z, 0);
73         break;
74     case 1:
75         mpz_set_si(result->z, templong->ob_digit[0]);
76         break;
77     default:
78         mpz_set_si(result->z, 0);
79 
80         if (Py_SIZE(templong) < 0) {
81             len = - Py_SIZE(templong);
82             negative = 1;
83         } else {
84             len = Py_SIZE(templong);
85             negative = 0;
86         }
87 
88         mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0,
89                    sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
90 
91         if (negative) {
92             mpz_neg(result->z, result->z);
93         }
94     }
95     return result;
96 }
97 
98 /* To support creation of temporary mpz objects. */
99 static void
mpz_set_PyIntOrLong(mpz_t z,PyObject * obj)100 mpz_set_PyIntOrLong(mpz_t z, PyObject *obj)
101 {
102     int negative;
103     Py_ssize_t len;
104     PyLongObject *templong = (PyLongObject*)obj;
105 
106 #ifdef PY2
107     if (PyInt_Check(obj)) {
108         mpz_set_si(z, PyInt_AS_LONG(obj));
109         return;
110     }
111 #endif
112 
113     switch (Py_SIZE(templong)) {
114     case -1:
115         mpz_set_si(z, -(sdigit)templong->ob_digit[0]);
116         break;
117     case 0:
118         mpz_set_si(z, 0);
119         break;
120     case 1:
121         mpz_set_si(z, templong->ob_digit[0]);
122         break;
123     default:
124         mpz_set_si(z, 0);
125 
126         if (Py_SIZE(templong) < 0) {
127             len = - Py_SIZE(templong);
128             negative = 1;
129         } else {
130             len = Py_SIZE(templong);
131             negative = 0;
132         }
133 
134         mpz_import(z, len, -1, sizeof(templong->ob_digit[0]), 0,
135                    sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
136 
137         if (negative) {
138             mpz_neg(z, z);
139         }
140     }
141     return;
142 }
143 
144 static MPZ_Object *
GMPy_MPZ_From_PyStr(PyObject * s,int base,CTXT_Object * context)145 GMPy_MPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
146 {
147     MPZ_Object *result;
148 
149     if (!(result = GMPy_MPZ_New(context))) {
150         /* LCOV_EXCL_START */
151         return NULL;
152         /* LCOV_EXCL_STOP */
153     }
154 
155     if (mpz_set_PyStr(result->z, s, base) == -1) {
156         Py_DECREF((PyObject*)result);
157         return NULL;
158     }
159     return result;
160 }
161 
162 static MPZ_Object *
GMPy_MPZ_From_PyFloat(PyObject * obj,CTXT_Object * context)163 GMPy_MPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
164 {
165     MPZ_Object *result;
166 
167     assert(PyFloat_Check(obj));
168 
169     if ((result = GMPy_MPZ_New(context))) {
170         double d = PyFloat_AsDouble(obj);
171 
172         if (Py_IS_NAN(d)) {
173             Py_DECREF((PyObject*)result);
174             VALUE_ERROR("'mpz' does not support NaN");
175             return NULL;
176         }
177         if (Py_IS_INFINITY(d)) {
178             Py_DECREF((PyObject*)result);
179             OVERFLOW_ERROR("'mpz' does not support Infinity");
180             return NULL;
181         }
182         mpz_set_d(result->z, d);
183     }
184     return result;
185 }
186 
187 static PyObject *
GMPy_PyLong_From_MPZ(MPZ_Object * obj,CTXT_Object * context)188 GMPy_PyLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
189 {
190     int negative;
191     size_t count, size;
192     PyLongObject *result;
193 
194     assert(CHECK_MPZANY(obj));
195 
196     /* Assume gmp uses limbs as least as large as the builtin longs do */
197     assert(mp_bits_per_limb >= PyLong_SHIFT);
198 
199     if (mpz_sgn(obj->z) < 0) {
200         negative = 1;
201     } else {
202         negative = 0;
203     }
204 
205     size = (mpz_sizeinbase(obj->z, 2) + PyLong_SHIFT - 1) / PyLong_SHIFT;
206 
207     if (!(result = _PyLong_New(size))) {
208         /* LCOV_EXCL_START */
209         return NULL;
210         /* LCOV_EXCL_STOP */
211     }
212 
213     mpz_export(result->ob_digit, &count, -1, sizeof(result->ob_digit[0]), 0,
214                sizeof(result->ob_digit[0])*8 - PyLong_SHIFT, obj->z);
215 
216     if (count == 0) {
217         result->ob_digit[0] = 0;
218     }
219 
220     /* long_normalize() is file-static so we must reimplement it */
221     /* longobjp = long_normalize(longobjp); */
222     while ((size>0) && (result->ob_digit[size-1] == 0)) {
223         size--;
224     }
225     Py_SIZE(result) = size;
226 
227     if (negative) {
228         Py_SIZE(result) = - Py_SIZE(result);
229     }
230     return (PyObject*)result;
231 }
232 
233 #ifdef PY2
234 static PyObject *
GMPy_MPZ_Long_Slot(MPZ_Object * self)235 GMPy_MPZ_Long_Slot(MPZ_Object *self)
236 {
237     return GMPy_PyLong_From_MPZ(self, NULL);
238 }
239 #endif
240 
241 /* The PyIntOrLong functions should be used when converting a number back
242  * to a Python value since is automatically returns an "int" or "long" when
243  * using Python 2.x. The PyLong_From functions (above) should only be used
244  * when a PyLong is specifically needed for Python 2.x.
245  */
246 
247 static PyObject *
GMPy_PyIntOrLong_From_MPZ(MPZ_Object * obj,CTXT_Object * context)248 GMPy_PyIntOrLong_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
249 {
250     assert(CHECK_MPZANY(obj));
251 
252 #ifdef PY2
253     if (mpz_fits_slong_p(obj->z)) {
254         /* cast is safe since we know it fits in a signed long */
255         return PyInt_FromLong((long)mpz_get_si(obj->z));
256     }
257 #endif
258 
259     return GMPy_PyLong_From_MPZ(obj, context);
260 }
261 
262 static PyObject *
GMPy_MPZ_Int_Slot(MPZ_Object * self)263 GMPy_MPZ_Int_Slot(MPZ_Object *self)
264 {
265     return GMPy_PyIntOrLong_From_MPZ(self, NULL);
266 }
267 
268 static PyObject *
GMPy_PyFloat_From_MPZ(MPZ_Object * obj,CTXT_Object * context)269 GMPy_PyFloat_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
270 {
271     double res;
272 
273     assert(CHECK_MPZANY(obj));
274 
275     res = mpz_get_d(obj->z);
276 
277     if (Py_IS_INFINITY(res)) {
278         OVERFLOW_ERROR("'mpz' too large to convert to float");
279         return NULL;
280     }
281 
282     return PyFloat_FromDouble(res);
283 }
284 
285 static PyObject *
GMPy_MPZ_Float_Slot(MPZ_Object * self)286 GMPy_MPZ_Float_Slot(MPZ_Object *self)
287 {
288     return GMPy_PyFloat_From_MPZ(self, NULL);
289 }
290 
291 static PyObject *
GMPy_PyStr_From_MPZ(MPZ_Object * obj,int base,int option,CTXT_Object * context)292 GMPy_PyStr_From_MPZ(MPZ_Object *obj, int base, int option, CTXT_Object *context)
293 {
294     assert(CHECK_MPZANY(obj));
295 
296     return mpz_ascii(obj->z, base, option, 0);
297 }
298 
299 static MPZ_Object *
GMPy_MPZ_From_Integer(PyObject * obj,CTXT_Object * context)300 GMPy_MPZ_From_Integer(PyObject *obj, CTXT_Object *context)
301 {
302     MPZ_Object *result = NULL;
303 
304     if (MPZ_Check(obj)) {
305         Py_INCREF(obj);
306         return (MPZ_Object*)obj;
307     }
308 
309     if (PyIntOrLong_Check(obj))
310         return GMPy_MPZ_From_PyIntOrLong(obj, context);
311 
312     if (XMPZ_Check(obj))
313         return GMPy_MPZ_From_XMPZ((XMPZ_Object*)obj, context);
314 
315     if (HAS_STRICT_MPZ_CONVERSION(obj)) {
316         result = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
317 
318         if (result != NULL && MPZ_Check(result)) {
319             return result;
320         }
321         else {
322             Py_XDECREF((PyObject*)result);
323             goto error;
324         }
325     }
326 
327   error:
328     TYPE_ERROR("cannot convert object to mpz");
329     return NULL;
330 }
331 
332 
333 
334 static MPZ_Object *
GMPy_MPZ_From_IntegerAndCopy(PyObject * obj,CTXT_Object * context)335 GMPy_MPZ_From_IntegerAndCopy(PyObject *obj, CTXT_Object *context)
336 {
337     MPZ_Object *result = NULL, *temp = NULL;
338 
339     result = GMPy_MPZ_From_Integer(obj, context);
340 
341     if (result == NULL)
342         return result;
343 
344     if (Py_REFCNT(result) == 1)
345         return result;
346 
347     if (!(temp = GMPy_MPZ_New(context))) {
348         /* LCOV_EXCL_START */
349         return NULL;
350         /* LCOV_EXCL_STOP */
351     }
352 
353     mpz_set(temp->z, result->z);
354     Py_DECREF((PyObject*)result);
355     return temp;
356 }
357 
358 /* str and repr implementations for mpz */
359 static PyObject *
GMPy_MPZ_Str_Slot(MPZ_Object * self)360 GMPy_MPZ_Str_Slot(MPZ_Object *self)
361 {
362     /* base-10, no tag */
363     return GMPy_PyStr_From_MPZ(self, 10, 0, NULL);
364 }
365 
366 static PyObject *
GMPy_MPZ_Repr_Slot(MPZ_Object * self)367 GMPy_MPZ_Repr_Slot(MPZ_Object *self)
368 {
369     /* base-10, with tag */
370     return GMPy_PyStr_From_MPZ(self, 10, 1, NULL);
371 }
372 
373 #ifdef SHARED
374 /* Helper function for argument parsing. Not used in static build. */
375 
376 static int
GMPy_MPZ_ConvertArg(PyObject * arg,PyObject ** ptr)377 GMPy_MPZ_ConvertArg(PyObject *arg, PyObject **ptr)
378 {
379     MPZ_Object *result = GMPy_MPZ_From_Integer(arg, NULL);
380 
381     if (result) {
382         *ptr = (PyObject*)result;
383         return 1;
384     }
385     else {
386         TYPE_ERROR("argument can not be converted to 'mpz'");
387         return 0;
388     }
389 }
390 #endif
391 
392 /* ======================================================================== *
393  * Conversion between native Python objects/MPZ and XMPZ.                   *
394  * ======================================================================== */
395 
396 static XMPZ_Object *
GMPy_XMPZ_From_PyIntOrLong(PyObject * obj,CTXT_Object * context)397 GMPy_XMPZ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
398 {
399     XMPZ_Object *result;
400     int negative;
401     Py_ssize_t len;
402     PyLongObject *templong = (PyLongObject*)obj;
403 
404     assert(PyIntOrLong_Check(obj));
405 
406     if(!(result = GMPy_XMPZ_New(context))) {
407         /* LCOV_EXCL_START */
408         return NULL;
409         /* LCOV_EXCL_STOP */
410     }
411 
412 #ifdef PY2
413     if (PyInt_Check(obj)) {
414         mpz_set_si(result->z, PyInt_AS_LONG(obj));
415         return result;
416     }
417 #endif
418 
419     switch (Py_SIZE(templong)) {
420     case -1:
421         mpz_set_si(result->z, -(sdigit)templong->ob_digit[0]);
422         break;
423     case 0:
424         mpz_set_si(result->z, 0);
425         break;
426     case 1:
427         mpz_set_si(result->z, templong->ob_digit[0]);
428         break;
429     default:
430         mpz_set_si(result->z, 0);
431 
432         if (Py_SIZE(templong) < 0) {
433             len = - Py_SIZE(templong);
434             negative = 1;
435         } else {
436             len = Py_SIZE(templong);
437             negative = 0;
438         }
439 
440         mpz_import(result->z, len, -1, sizeof(templong->ob_digit[0]), 0,
441                    sizeof(templong->ob_digit[0])*8 - PyLong_SHIFT, templong->ob_digit);
442 
443         if (negative) {
444             mpz_neg(result->z, result->z);
445         }
446     }
447     return result;
448 }
449 
450 static XMPZ_Object *
GMPy_XMPZ_From_PyStr(PyObject * s,int base,CTXT_Object * context)451 GMPy_XMPZ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
452 {
453     XMPZ_Object *result;
454 
455     if (!(result = GMPy_XMPZ_New(context)))
456         return NULL;
457 
458     if (mpz_set_PyStr(result->z, s, base) == -1) {
459         Py_DECREF((PyObject*)result);
460         return NULL;
461     }
462     return result;
463 }
464 
465 static XMPZ_Object *
GMPy_XMPZ_From_PyFloat(PyObject * obj,CTXT_Object * context)466 GMPy_XMPZ_From_PyFloat(PyObject *obj, CTXT_Object *context)
467 {
468     XMPZ_Object *result;
469 
470     assert(PyFloat_Check(obj));
471 
472     if ((result = GMPy_XMPZ_New(context))) {
473         double d = PyFloat_AsDouble(obj);
474 
475         if (Py_IS_NAN(d)) {
476             Py_DECREF((PyObject*)result);
477             VALUE_ERROR("'xmpz' does not support NaN");
478             return NULL;
479         }
480         if (Py_IS_INFINITY(d)) {
481             Py_DECREF((PyObject*)result);
482             OVERFLOW_ERROR("'xmpz' does not support Infinity");
483             return NULL;
484         }
485         mpz_set_d(result->z, d);
486     }
487     return result;
488 }
489 
490 static XMPZ_Object *
GMPy_XMPZ_From_MPZ(MPZ_Object * obj,CTXT_Object * context)491 GMPy_XMPZ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
492 {
493     XMPZ_Object *result;
494 
495     assert(CHECK_MPZANY(obj));
496 
497     if ((result = GMPy_XMPZ_New(context)))
498         mpz_set(result->z, obj->z);
499 
500     return result;
501 }
502 
503 static XMPZ_Object *
GMPy_XMPZ_From_XMPZ(XMPZ_Object * obj,CTXT_Object * context)504 GMPy_XMPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
505 {
506     XMPZ_Object *result;
507 
508     assert(XMPZ_Check(obj));
509 
510     if ((result = GMPy_XMPZ_New(context)))
511         mpz_set(result->z, obj->z);
512 
513     return result;
514 }
515 
516 static PyObject *
GMPy_PyStr_From_XMPZ(XMPZ_Object * obj,int base,int option,CTXT_Object * context)517 GMPy_PyStr_From_XMPZ(XMPZ_Object *obj, int base, int option, CTXT_Object *context)
518 {
519     assert(XMPZ_Check(obj));
520 
521     return mpz_ascii(obj->z, base, option, 1);
522 }
523 
524 static MPZ_Object *
GMPy_MPZ_From_XMPZ(XMPZ_Object * obj,CTXT_Object * context)525 GMPy_MPZ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
526 {
527     MPZ_Object *result;
528 
529     assert(XMPZ_Check(obj));
530 
531     if ((result = GMPy_MPZ_New(context)))
532         mpz_set(result->z, obj->z);
533 
534     return result;
535 }
536 
537 /* str and repr implementations for xmpz */
538 static PyObject *
GMPy_XMPZ_Str_Slot(XMPZ_Object * self)539 GMPy_XMPZ_Str_Slot(XMPZ_Object *self)
540 {
541     /* base-10, no tag */
542     return GMPy_PyStr_From_XMPZ(self, 10, 0, NULL);
543 }
544 
545 static PyObject *
GMPy_XMPZ_Repr_Slot(XMPZ_Object * self)546 GMPy_XMPZ_Repr_Slot(XMPZ_Object *self)
547 {
548     /* base-10, with tag */
549     return GMPy_PyStr_From_XMPZ(self, 10, 1, NULL);
550 }
551 
552 /* ======================================================================== *
553  * Conversion between native Python objects/MPZ/XMPZ and MPQ.               *
554  * ======================================================================== */
555 
556 static MPQ_Object *
GMPy_MPQ_From_PyIntOrLong(PyObject * obj,CTXT_Object * context)557 GMPy_MPQ_From_PyIntOrLong(PyObject *obj, CTXT_Object *context)
558 {
559     MPQ_Object *result;
560     MPZ_Object *temp;
561 
562     assert(PyIntOrLong_Check(obj));
563 
564     temp = GMPy_MPZ_From_PyIntOrLong(obj, context);
565 
566     if (!temp)
567         return NULL;
568 
569     if ((result = GMPy_MPQ_New(context))) {
570         mpq_set_z(result->q, temp->z);
571         Py_DECREF((PyObject*)temp);
572     }
573     return result;
574 }
575 
576 static MPQ_Object *
GMPy_MPQ_From_PyStr(PyObject * s,int base,CTXT_Object * context)577 GMPy_MPQ_From_PyStr(PyObject *s, int base, CTXT_Object *context)
578 {
579     MPQ_Object *result;
580     char *cp;
581     char exp_char = 'E';
582     Py_ssize_t len, i;
583     PyObject *ascii_str = NULL;
584     long expt = 0;
585 
586     if (!(result = GMPy_MPQ_New(context))) {
587         /* LCOV_EXCL_START */
588         return NULL;
589         /* LCOV_EXCL_STOP */
590     }
591 
592     if (PyBytes_Check(s)) {
593         len = PyBytes_Size(s);
594         cp = PyBytes_AsString(s);
595     }
596     else if (PyUnicode_Check(s)) {
597         ascii_str = PyUnicode_AsASCIIString(s);
598         if (!ascii_str) {
599             VALUE_ERROR("string contains non-ASCII characters");
600             goto error;
601         }
602         len = PyBytes_Size(ascii_str);
603         cp = PyBytes_AsString(ascii_str);
604     }
605     else {
606         TYPE_ERROR("object is not string or Unicode");
607         goto error;
608     }
609 
610     /* Don't allow NULL characters */
611     for (i = 0; i < len; i++) {
612         if (cp[i] == '\0') {
613             VALUE_ERROR("string contains NULL characters");
614             goto error;
615         }
616     }
617 
618     {
619         char *whereslash = strchr((char*)cp, '/');
620         char *wheredot = strchr((char*)cp, '.');
621         char *whereexp = strchr((char*)cp, 'E');
622 
623         if (!whereexp) {
624             whereexp = strchr((char*)cp, 'e');
625             exp_char = 'e';
626         }
627 
628         if (whereslash && wheredot) {
629             VALUE_ERROR("illegal string: both . and / found");
630             goto error;
631         }
632 
633         if (wheredot && (base != 10)) {
634             VALUE_ERROR("illegal string: embedded . requires base=10");
635             goto error;
636         }
637 
638         /* If base=10, no slash is found, and an exponent symbol is found, then
639          * assume we have decimal number in scientific format.
640          */
641         if (whereexp && !whereslash && (base == 10)) {
642             /* Temporarily shorten the string and continue processing as
643              * normal. We'll deal with the exponent later.
644              */
645             *whereexp = '\0';
646             expt = atol(whereexp+1);
647         }
648 
649         /* Handle the case where an embedded decimal point exists. An optional
650          * exponent is also allowed. We take advantage of the fact that
651          * mpz_set_str() ignores embedded space characters. We count the
652          * number of digits after the decimal point and then replace the '.'
653          * with a ' '. We've already inserted a NUL byte to terminate the
654          * string in the case when an exponent was entered. The value for
655          * the exponent has already been read.
656          */
657 
658         if (wheredot) {
659             char *counter;
660             long digits = 0;
661 
662             counter = wheredot;
663             digits = 0;
664             *wheredot = ' ';
665             while (*++counter != '\0') {
666                 if (isdigit(*counter))
667                     digits++;
668             }
669             if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
670                 if (wheredot)
671                     *wheredot = '.';
672                 /* Restore the exponent! */
673                 if (whereexp && !whereslash && (base == 10))
674                     *whereexp = exp_char;
675                 VALUE_ERROR("invalid digits");
676                 goto error;
677             }
678             /* Process the exponent. */
679             digits = expt - digits;
680             if (digits < 0) {
681                 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-digits));
682             }
683             else {
684                 /* Use the denominator instead of a temporary variable. */
685                 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(digits));
686                 mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
687                 mpz_set_ui(mpq_denref(result->q), 1);
688             }
689             mpq_canonicalize(result->q);
690 
691             /* Restore the decimal point. */
692             *wheredot = '.';
693 
694             /* Restore the exponent! */
695             if (whereexp && (base == 10))
696                 *whereexp = exp_char;
697 
698             goto finish;
699         }
700 
701         if (whereslash)
702             *whereslash = '\0';
703 
704         /* Read the numerator. */
705         if (-1 == mpz_set_str(mpq_numref(result->q), (char*)cp, base)) {
706             if (whereslash)
707                 *whereslash = '/';
708             VALUE_ERROR("invalid digits");
709             goto error;
710         }
711 
712         /* If a slash was present, read the denominator. */
713         if (whereslash) {
714             *whereslash = '/';
715             if (-1 == mpz_set_str(mpq_denref(result->q), whereslash+1, base)) {
716                 VALUE_ERROR("invalid digits");
717                 goto error;
718             }
719             if (0 == mpz_sgn(mpq_denref(result->q))) {
720                 ZERO_ERROR("zero denominator in mpq()");
721                 goto error;
722             }
723             mpq_canonicalize(result->q);
724         }
725         else {
726             /* Since no slash was present, either the denominator is 1 or a
727              * power of 10.
728              */
729 
730             if (expt <= 0) {
731                 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(-expt));
732             }
733             else {
734                 mpz_ui_pow_ui(mpq_denref(result->q), 10, (unsigned long)(expt));
735                 mpz_mul(mpq_numref(result->q), mpq_numref(result->q), mpq_denref(result->q));
736                 mpz_set_ui(mpq_denref(result->q), 1);
737             }
738             mpq_canonicalize(result->q);
739             if (whereexp && (base == 10))
740                 *whereexp = exp_char;
741         }
742     }
743 
744   finish:
745     Py_XDECREF(ascii_str);
746     return result;
747 
748   error:
749     Py_DECREF((PyObject*)result);
750     Py_XDECREF(ascii_str);
751     return NULL;
752 }
753 
754 static MPQ_Object *
GMPy_MPQ_From_PyFloat(PyObject * obj,CTXT_Object * context)755 GMPy_MPQ_From_PyFloat(PyObject *obj, CTXT_Object *context)
756 {
757     MPQ_Object *result;
758 
759     assert(PyFloat_Check(obj));
760 
761     if ((result = GMPy_MPQ_New(context))) {
762         double d = PyFloat_AsDouble(obj);
763 
764         if (Py_IS_NAN(d)) {
765             Py_DECREF((PyObject*)result);
766             VALUE_ERROR("'mpq' does not support NaN");
767             return NULL;
768         }
769         if (Py_IS_INFINITY(d)) {
770             Py_DECREF((PyObject*)result);
771             OVERFLOW_ERROR("'mpq' does not support Infinity");
772             return NULL;
773         }
774         mpq_set_d(result->q, d);
775     }
776 
777     return result;
778 }
779 
780 static MPQ_Object *
GMPy_MPQ_From_MPZ(MPZ_Object * obj,CTXT_Object * context)781 GMPy_MPQ_From_MPZ(MPZ_Object *obj, CTXT_Object *context)
782 {
783     MPQ_Object *result;
784 
785     assert(CHECK_MPZANY(obj));
786 
787     if ((result = GMPy_MPQ_New(context)))
788         mpq_set_z(result->q, obj->z);
789 
790     return result;
791 }
792 
793 static MPQ_Object *
GMPy_MPQ_From_XMPZ(XMPZ_Object * obj,CTXT_Object * context)794 GMPy_MPQ_From_XMPZ(XMPZ_Object *obj, CTXT_Object *context)
795 {
796     MPQ_Object *result;
797 
798     assert(XMPZ_Check(obj));
799 
800     if ((result = GMPy_MPQ_New(context)))
801         mpq_set_z(result->q, obj->z);
802 
803     return result;
804 }
805 
806 static MPZ_Object *
GMPy_MPZ_From_MPQ(MPQ_Object * obj,CTXT_Object * context)807 GMPy_MPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
808 {
809     MPZ_Object *result;
810 
811     assert(MPQ_Check(obj));
812 
813     if ((result = GMPy_MPZ_New(context)))
814         mpz_set_q(result->z, obj->q);
815 
816     return result;
817 }
818 
819 static XMPZ_Object *
GMPy_XMPZ_From_MPQ(MPQ_Object * obj,CTXT_Object * context)820 GMPy_XMPZ_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
821 {
822     XMPZ_Object *result;
823 
824     assert(MPQ_Check(obj));
825 
826     if ((result = GMPy_XMPZ_New(context)))
827 
828         mpz_set_q(result->z, obj->q);
829 
830     return result;
831 }
832 #ifdef PY2
833 static PyObject *
GMPy_PyLong_From_MPQ(MPQ_Object * obj,CTXT_Object * context)834 GMPy_PyLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
835 {
836     PyObject *result;
837     MPZ_Object *temp;
838 
839     assert(MPQ_Check(obj));
840 
841     temp = GMPy_MPZ_From_MPQ(obj, context);
842 
843     if (!temp) {
844         /* LCOV_EXCL_START */
845         return NULL;
846         /* LCOV_EXCL_STOP */
847     }
848 
849     result = GMPy_PyLong_From_MPZ(temp, context);
850     Py_DECREF((PyObject*)temp);
851 
852     return result;
853 }
854 
855 static PyObject *
GMPy_MPQ_Long_Slot(MPQ_Object * self)856 GMPy_MPQ_Long_Slot(MPQ_Object *self)
857 {
858     return GMPy_PyLong_From_MPQ(self, NULL);
859 }
860 #endif
861 
862 static PyObject *
GMPy_PyIntOrLong_From_MPQ(MPQ_Object * obj,CTXT_Object * context)863 GMPy_PyIntOrLong_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
864 {
865     PyObject *result;
866     MPZ_Object *temp;
867 
868     assert(MPQ_Check(obj));
869 
870     temp = GMPy_MPZ_From_MPQ(obj, context);
871 
872     if (!temp) {
873         /* LCOV_EXCL_START */
874         return NULL;
875         /* LCOV_EXCL_STOP */
876     }
877 
878     result = GMPy_PyIntOrLong_From_MPZ(temp, context);
879     Py_DECREF((PyObject*)temp);
880 
881     return result;
882 }
883 
884 static PyObject *
GMPy_MPQ_Int_Slot(MPQ_Object * self)885 GMPy_MPQ_Int_Slot(MPQ_Object *self)
886 {
887     return GMPy_PyIntOrLong_From_MPQ(self, NULL);
888 }
889 
890 static char* _qtag = "mpq(";
891 
892 static PyObject *
GMPy_PyStr_From_MPQ(MPQ_Object * obj,int base,int option,CTXT_Object * context)893 GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context)
894 {
895     PyObject *result = NULL, *numstr = NULL, *denstr = NULL;
896     char buffer[50], *p;
897 
898     numstr = mpz_ascii(mpq_numref(obj->q), base, 0, 0);
899     if (!numstr) {
900         /* LCOV_EXCL_START */
901         return NULL;
902         /* LCOV_EXCL_STOP */
903     }
904 
905     /* Check if denominator is 1 and no tag is requested. If so, just
906      * return the numerator.
907      */
908     if (!(option & 1) && (0 == mpz_cmp_ui(mpq_denref(obj->q),1)))
909         return numstr;
910 
911     denstr = mpz_ascii(mpq_denref(obj->q), base, 0, 0);
912     if (!denstr) {
913         /* LCOV_EXCL_START */
914         Py_DECREF(numstr);
915         return NULL;
916         /* LCOV_EXCL_STOP */
917     }
918 
919     /* Build the format string. */
920     p = buffer;
921     if (option & 1) {
922         strcpy(p, _qtag);
923         p += strlen(p);
924     }
925 
926 #ifdef PY2
927     *(p++) = '%';
928     *(p++) = 's';
929     if (option & 1)
930         *(p++) = ',';
931     else
932         *(p++) = '/';
933     *(p++) = '%';
934     *(p++) = 's';
935     if (option & 1)
936         *(p++) = ')';
937     *(p++) = '\00';
938     result = PyString_FromFormat(buffer, PyString_AS_STRING(numstr),
939                                  PyString_AS_STRING(denstr));
940 #else
941     *(p++) = '%';
942     *(p++) = 'U';
943     if (option & 1)
944         *(p++) = ',';
945     else
946         *(p++) = '/';
947     *(p++) = '%';
948     *(p++) = 'U';
949     if (option & 1)
950         *(p++) = ')';
951     *(p++) = '\00';
952     result = PyUnicode_FromFormat(buffer, numstr, denstr);
953 #endif
954     Py_DECREF(numstr);
955     Py_DECREF(denstr);
956     return result;
957 }
958 
959 static PyObject *
GMPy_PyFloat_From_MPQ(MPQ_Object * obj,CTXT_Object * context)960 GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
961 {
962     double res;
963 
964     assert(MPQ_Check(obj));
965 
966     res = mpq_get_d(obj->q);
967 
968     if (Py_IS_INFINITY(res)) {
969         OVERFLOW_ERROR("'mpq' too large to convert to float");
970         return NULL;
971     }
972 
973     return PyFloat_FromDouble(res);
974 }
975 
976 static PyObject *
GMPy_MPQ_Float_Slot(MPQ_Object * self)977 GMPy_MPQ_Float_Slot(MPQ_Object *self)
978 {
979     return GMPy_PyFloat_From_MPQ(self, NULL);
980 }
981 
982 static MPQ_Object*
GMPy_MPQ_From_Fraction(PyObject * obj,CTXT_Object * context)983 GMPy_MPQ_From_Fraction(PyObject* obj, CTXT_Object *context)
984 {
985     MPQ_Object *result;
986     PyObject *num, *den;
987 
988     if (!(result = GMPy_MPQ_New(context))) {
989         /* LCOV_EXCL_START */
990         return NULL;
991         /* LCOV_EXCL_STOP */
992     }
993     mpq_set_si(result->q, 0, 1);
994 
995     num = PyObject_GetAttrString(obj, "numerator");
996     den = PyObject_GetAttrString(obj, "denominator");
997     if (!num || !PyIntOrLong_Check(num) || !den || !PyIntOrLong_Check(den)) {
998         SYSTEM_ERROR("Object does not appear to be Fraction");
999         Py_XDECREF(num);
1000         Py_XDECREF(den);
1001         Py_DECREF((PyObject*)result);
1002         return NULL;
1003     }
1004     mpz_set_PyIntOrLong(mpq_numref(result->q), num);
1005     mpz_set_PyIntOrLong(mpq_denref(result->q), den);
1006     Py_DECREF(num);
1007     Py_DECREF(den);
1008     return result;
1009 }
1010 
1011 static MPQ_Object*
GMPy_MPQ_From_Number(PyObject * obj,CTXT_Object * context)1012 GMPy_MPQ_From_Number(PyObject *obj, CTXT_Object *context)
1013 {
1014     if (MPQ_Check(obj)) {
1015         Py_INCREF(obj);
1016         return (MPQ_Object*)obj;
1017     }
1018 
1019     if (MPZ_Check(obj))
1020         return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
1021 
1022     if (MPFR_Check(obj))
1023         return GMPy_MPQ_From_MPFR((MPFR_Object*)obj, context);
1024 
1025     if (PyFloat_Check(obj))
1026         return GMPy_MPQ_From_PyFloat(obj, context);
1027 
1028     if (PyIntOrLong_Check(obj))
1029         return GMPy_MPQ_From_PyIntOrLong(obj, context);
1030 
1031     if (XMPZ_Check(obj))
1032         return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
1033 
1034     if (IS_FRACTION(obj))
1035         return GMPy_MPQ_From_Fraction(obj, context);
1036 
1037     if (HAS_MPQ_CONVERSION(obj)) {
1038         MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
1039 
1040         if (res != NULL && MPQ_Check(res)) {
1041             return res;
1042         }
1043         else {
1044             Py_XDECREF((PyObject*)res);
1045             goto error;
1046         }
1047     }
1048 
1049     if (HAS_MPZ_CONVERSION(obj)) {
1050         MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
1051 
1052         if (res != NULL && MPZ_Check(res)) {
1053             MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
1054             Py_DECREF(res);
1055             return temp;
1056         }
1057         else {
1058             Py_XDECREF((PyObject*)res);
1059             goto error;
1060         }
1061     }
1062 
1063   error:
1064     TYPE_ERROR("cannot convert object to mpq");
1065     return NULL;
1066 }
1067 
1068 static MPQ_Object*
GMPy_MPQ_From_RationalAndCopy(PyObject * obj,CTXT_Object * context)1069 GMPy_MPQ_From_RationalAndCopy(PyObject *obj, CTXT_Object *context)
1070 {
1071     MPQ_Object *result = NULL, *temp = NULL;
1072 
1073     result = GMPy_MPQ_From_Rational(obj, context);
1074 
1075     if (result == NULL)
1076         return result;
1077 
1078     if (Py_REFCNT(result) == 1)
1079         return result;
1080 
1081     if (!(temp = GMPy_MPQ_New(context))) {
1082         /* LCOV_EXCL_START */
1083         return NULL;
1084         /* LCOV_EXCL_STOP */
1085     }
1086 
1087     mpq_set(temp->q, result->q);
1088     Py_DECREF((PyObject*)result);
1089     return temp;
1090 }
1091 
1092 static MPQ_Object*
GMPy_MPQ_From_Rational(PyObject * obj,CTXT_Object * context)1093 GMPy_MPQ_From_Rational(PyObject *obj, CTXT_Object *context)
1094 {
1095     if (MPQ_Check(obj)) {
1096         Py_INCREF(obj);
1097         return (MPQ_Object*)obj;
1098     }
1099 
1100     if (MPZ_Check(obj))
1101         return GMPy_MPQ_From_MPZ((MPZ_Object*)obj, context);
1102 
1103     if (PyIntOrLong_Check(obj))
1104         return GMPy_MPQ_From_PyIntOrLong(obj, context);
1105 
1106     if (XMPZ_Check(obj))
1107         return GMPy_MPQ_From_XMPZ((XMPZ_Object*)obj, context);
1108 
1109     if (IS_FRACTION(obj))
1110         return GMPy_MPQ_From_Fraction(obj, context);
1111 
1112     if (HAS_MPQ_CONVERSION(obj)) {
1113         MPQ_Object * res = (MPQ_Object *) PyObject_CallMethod(obj, "__mpq__", NULL);
1114 
1115         if (res != NULL && MPQ_Check(res)) {
1116             return res;
1117         }
1118         else {
1119             Py_XDECREF((PyObject*)res);
1120             goto error;
1121         }
1122     }
1123 
1124     if (HAS_MPZ_CONVERSION(obj)) {
1125         MPZ_Object * res = (MPZ_Object *) PyObject_CallMethod(obj, "__mpz__", NULL);
1126 
1127         if (res != NULL && MPZ_Check(res)) {
1128             MPQ_Object * temp = GMPy_MPQ_From_MPZ(res, context);
1129             Py_DECREF(res);
1130             return temp;
1131         }
1132         else {
1133             Py_XDECREF((PyObject*)res);
1134             goto error;
1135         }
1136     }
1137 
1138   error:
1139     TYPE_ERROR("cannot convert object to mpq");
1140     return NULL;
1141 }
1142 
1143 /*
1144  * coerce any number to a mpq
1145  */
1146 
1147 #ifdef SHARED
1148 /* Helper function for argument parsing. Not used in static build. */
1149 
1150 int
GMPy_MPQ_ConvertArg(PyObject * arg,PyObject ** ptr)1151 GMPy_MPQ_ConvertArg(PyObject *arg, PyObject **ptr)
1152 {
1153     MPQ_Object* result = GMPy_MPQ_From_Number(arg, NULL);
1154 
1155     if (result) {
1156         *ptr = (PyObject*)result;
1157         return 1;
1158     }
1159     else {
1160         if (!PyErr_Occurred()) {
1161             TYPE_ERROR("argument can not be converted to 'mpq'");
1162         }
1163         return 0;
1164     }
1165 }
1166 
1167 #endif
1168 
1169 /* str and repr implementations for mpq */
1170 static PyObject *
GMPy_MPQ_Str_Slot(MPQ_Object * self)1171 GMPy_MPQ_Str_Slot(MPQ_Object *self)
1172 {
1173     /* base-10, no tag */
1174     return GMPy_PyStr_From_MPQ(self, 10, 0, NULL);
1175 }
1176 
1177 static PyObject *
GMPy_MPQ_Repr_Slot(MPQ_Object * self)1178 GMPy_MPQ_Repr_Slot(MPQ_Object *self)
1179 {
1180     /* base-10, with tag */
1181     return GMPy_PyStr_From_MPQ(self, 10, 1, NULL);
1182 }
1183 
1184