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