gmpy2_binary.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 * gmpy2_binary.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 /* Conversion routines between GMPY2 objects and a compact, portable 28 * binary representation. The binary format of GMPY2 is not compatible 29 * with GMPY 1.x. Methods to read the old format are provided. 30 */ 31 32 /* Provide functions to access the old binary formats. */ 33 34 PyDoc_STRVAR(doc_mpz_from_old_binary, 35 "mpz_from_old_binary(string) -> mpz\n\n" 36 "Return an 'mpz' from a GMPY 1.x binary format."); 37 38 static PyObject * 39 GMPy_MPZ_From_Old_Binary(PyObject *self, PyObject *other) 40 { 41 unsigned char *cp; 42 Py_ssize_t len; 43 int negative = 0; 44 MPZ_Object *result; 45 46 if (!(PyBytes_Check(other))) { 47 TYPE_ERROR("mpz_from_old_binary() requires bytes argument"); 48 return NULL; 49 } 50 51 if (!(result = GMPy_MPZ_New(NULL))) { 52 /* LCOV_EXCL_START */ 53 return NULL; 54 /* LCOV_EXCL_STOP */ 55 } 56 57 len = PyBytes_Size(other); 58 cp = (unsigned char*)PyBytes_AsString(other); 59 60 if (cp[len-1] == 0xFF) { 61 negative = 1; 62 --len; 63 } 64 mpz_import(result->z, len, -1, sizeof(char), 0, 0, cp); 65 if (negative) 66 mpz_neg(result->z, result->z); 67 return (PyObject*)result; 68 } 69 70 PyDoc_STRVAR(doc_mpq_from_old_binary, 71 "mpq_from_old_binary(string) -> mpq\n\n" 72 "Return an 'mpq' from a GMPY 1.x binary format."); 73 74 static PyObject * 75 GMPy_MPQ_From_Old_Binary(PyObject *self, PyObject *other) 76 { 77 unsigned char *cp; 78 Py_ssize_t len; 79 int topper, negative, numlen; 80 mpz_t numerator, denominator; 81 MPQ_Object *result; 82 83 if (!(PyBytes_Check(other))) { 84 TYPE_ERROR("mpq_from_old_binary() requires bytes argument"); 85 return NULL; 86 } 87 88 if (!(result = GMPy_MPQ_New(NULL))) { 89 /* LCOV_EXCL_START */ 90 return NULL; 91 /* LCOV_EXCL_STOP */ 92 } 93 94 len = PyBytes_Size(other); 95 cp = (unsigned char*)PyBytes_AsString(other); 96 97 if (len < 6) { 98 VALUE_ERROR("invalid mpq binary (too short)"); 99 Py_DECREF((PyObject*)result); 100 return NULL; 101 } 102 103 topper = cp[3] & 0x7f; 104 negative = cp[3] & 0x80; 105 numlen = cp[0] + 256 * (cp[1] + 256 * (cp[2] + 256 * topper)); 106 if (len < (4 + numlen + 1)) { 107 VALUE_ERROR("invalid mpq binary (num len)"); 108 Py_DECREF((PyObject*)result); 109 return NULL; 110 } 111 112 mpz_init(numerator); 113 mpz_init(denominator); 114 mpz_import(numerator, numlen, -1, sizeof(char), 0, 0, cp+4); 115 mpz_import(denominator, len-4-numlen, -1, sizeof(char), 0, 0, cp+4+numlen); 116 if (negative) 117 mpz_neg(numerator, numerator); 118 119 mpq_set_num(result->q, numerator); 120 mpq_set_den(result->q, denominator); 121 mpq_canonicalize(result->q); 122 mpz_clear(numerator); 123 mpz_clear(denominator); 124 return (PyObject*)result; 125 } 126 127 PyDoc_STRVAR(doc_mpfr_from_old_binary, 128 "mpfr_from_old_binary(string) -> mpfr\n\n" 129 "Return an 'mpfr' from a GMPY 1.x binary mpf format."); 130 131 static PyObject * 132 GMPy_MPFR_From_Old_Binary(PyObject *self, PyObject *other) 133 { 134 unsigned char *cp; 135 Py_ssize_t len; 136 MPFR_Object *result; 137 mpfr_t digit; 138 mpfr_prec_t prec; 139 int i, codebyte, resusign, exposign, resuzero, precilen; 140 unsigned int expomag = 0; 141 CTXT_Object *context = NULL; 142 143 CHECK_CONTEXT(context); 144 145 if (!(PyBytes_Check(other))) { 146 TYPE_ERROR("mpfr_from_old_binary() requires bytes argument"); 147 return NULL; 148 } 149 150 len = PyBytes_Size(other); 151 cp = (unsigned char*)PyBytes_AsString(other); 152 153 if (len == 1) { 154 prec = 0; 155 } 156 else { 157 prec = (mpfr_prec_t)(8 * (len - 5)); 158 if ((len>=5) && (cp[0]&8)) { 159 prec = 0; 160 for (i=4; i>0; --i) { 161 prec = (prec << 8) | cp[i]; 162 } 163 } 164 } 165 166 /* 167 * binary format for MP floats: first, a code-byte, then, a LSB 168 * 4-byte unsigned int (exponent magnitude), then the "mantissa" 169 * (actually, "significand", but "mantissa" is the usual term...) 170 * in MSB form. 171 * 172 * The codebyte encodes both the signs, exponent and result, or 173 * also the zeroness of the result (in which case, nothing more). 174 */ 175 codebyte = cp[0]; 176 resusign = codebyte & 1; 177 exposign = codebyte & 2; 178 resuzero = codebyte & 4; 179 precilen = (codebyte & 8)?4:0; 180 181 /* mpfr zero has a very compact (1-byte) binary encoding!-) */ 182 if (resuzero) { 183 if (!(result = GMPy_MPFR_New(prec, context))) { 184 /* LCOV_EXCL_START */ 185 return NULL; 186 /* LCOV_EXCL_STOP */ 187 } 188 result->rc = mpfr_set_ui(result->f, 0, MPFR_RNDN); 189 return (PyObject*)result; 190 } 191 192 /* all other numbers are 6+ bytes: codebyte, 4-byte exp, 1+ 193 * bytes for the mantissa; check this string is 6+ bytes 194 */ 195 if (len < 6 + precilen) { 196 VALUE_ERROR("invalid mpf binary encoding (too short)"); 197 return NULL; 198 } 199 200 if (!(result = GMPy_MPFR_New(prec, context))) { 201 /* LCOV_EXCL_START */ 202 return NULL; 203 /* LCOV_EXCL_STOP */ 204 } 205 206 /* reconstruct exponent */ 207 for (i = 4 + precilen; i > precilen; --i) { 208 expomag = (expomag<<8) | cp[i]; 209 } 210 211 /* reconstruct 'mantissa' (significand) */ 212 mpfr_set_si(result->f, 0, MPFR_RNDN); 213 mpfr_init2(digit, prec); 214 for (i = 5 + precilen; i<len; i++) { 215 mpfr_set_ui(digit, cp[i], MPFR_RNDN); 216 mpfr_div_2ui(digit, digit, (unsigned long)((i-4-precilen) * 8), 217 context->ctx.mpfr_round); 218 mpfr_add(result->f, result->f, digit, MPFR_RNDN); 219 } 220 mpfr_clear(digit); 221 /* apply exponent, with its appropriate sign */ 222 if (exposign) 223 mpfr_div_2ui(result->f, result->f, 8*expomag, MPFR_RNDN); 224 else 225 mpfr_mul_2ui(result->f, result->f, 8*expomag, MPFR_RNDN); 226 /* apply significand-sign (sign of the overall number) */ 227 if (resusign) 228 mpfr_neg(result->f, result->f, MPFR_RNDN); 229 230 return (PyObject*)result; 231 } 232 233 /* Format of the binary representation of an mpz/xmpz. 234 * 235 * byte[0]: 1 => mpz 236 * 2 => xmpz 237 * 3 => mpq (see Pympq_To_Binary) 238 * 4 => mpfr (see Pympfr_To_Binary) 239 * 5 => mpc (see Pympc_To_Binary) 240 * byte[1:0-1]: 0 => value is 0 241 * 1 => value is > 0 242 * 2 => value is < 0 243 * 3 => unassigned 244 * byte[2]+: value 245 */ 246 247 static PyObject * 248 GMPy_MPZ_To_Binary(MPZ_Object *self) 249 { 250 size_t size = 2; 251 int sgn; 252 char *buffer; 253 PyObject *result; 254 255 sgn = mpz_sgn(self->z); 256 if (sgn == 0) { 257 TEMP_ALLOC(buffer, size); 258 buffer[0] = 0x01; 259 buffer[1] = 0x00; 260 goto done; 261 } 262 263 size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2; 264 265 TEMP_ALLOC(buffer, size); 266 buffer[0] = 0x01; 267 if (sgn > 0) 268 buffer[1] = 0x01; 269 else 270 buffer[1] = 0x02; 271 mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z); 272 273 done: 274 result = PyBytes_FromStringAndSize(buffer, size); 275 TEMP_FREE(buffer, size); 276 return result; 277 } 278 279 static PyObject * 280 GMPy_XMPZ_To_Binary(XMPZ_Object *self) 281 { 282 size_t size = 2; 283 int sgn; 284 char *buffer; 285 PyObject *result; 286 287 sgn = mpz_sgn(self->z); 288 if (sgn == 0) { 289 TEMP_ALLOC(buffer, size); 290 buffer[0] = 0x02; 291 buffer[1] = 0x00; 292 goto done; 293 } 294 295 size = ((mpz_sizeinbase(self->z, 2) + 7) / 8) + 2; 296 297 TEMP_ALLOC(buffer, size); 298 buffer[0] = 0x02; 299 if (sgn > 0) 300 buffer[1] = 0x01; 301 else 302 buffer[1] = 0x02; 303 mpz_export(buffer+2, NULL, -1, sizeof(char), 0, 0, self->z); 304 305 done: 306 result = PyBytes_FromStringAndSize(buffer, size); 307 TEMP_FREE(buffer, size); 308 return result; 309 } 310 311 /* Format of the binary representation of an mpq. 312 * 313 * byte[0]: 1 => mpz (see Pympz_To_Binary) 314 * 2 => xmpz (see Pyxmpz_To_Binary) 315 * 3 => mpq 316 * 4 => mpfr (see Pympfr_To_Binary) 317 * 5 => mpc (see Pympc_To_Binary) 318 * byte[1:0-1]: 0 => value is 0 319 * 1 => value is > 0 320 * 2 => value is < 0 321 * 3 => unassigned 322 * byte[1:2-2]: 0 => 32-bit length (n=4) 323 * 1 => 64-bit length (n=8) 324 * byte[2+]: numerator length, using either 4 or 8 bytes 325 * byte[2+n]+: numerator, followed by denominator 326 */ 327 328 static PyObject * 329 GMPy_MPQ_To_Binary(MPQ_Object *self) 330 { 331 size_t sizenum, sizeden, sizesize = 4, size = 2, sizetemp, i; 332 size_t count = 0; 333 int sgn; 334 char *buffer, large = 0x00; 335 PyObject *result = 0; 336 337 sgn = mpq_sgn(self->q); 338 if (sgn == 0) { 339 TEMP_ALLOC(buffer, size); 340 buffer[0] = 0x03; 341 buffer[1] = 0x00; 342 goto done; 343 } 344 345 sizenum = (mpz_sizeinbase(mpq_numref(self->q), 2) + 7) / 8; 346 sizeden = (mpz_sizeinbase(mpq_denref(self->q), 2) + 7) / 8; 347 size = sizenum + sizeden + 2; 348 349 /* Check if sizenum larger than 32 bits. */ 350 if ((sizenum >> 16) >> 16) { 351 /* Current versions of GMP do not allow values to be this large. The 352 * test is left to (possibly) support future versions that support 353 * larger values. 354 */ 355 /* LCOV_EXCL_START */ 356 large = 0x04; 357 sizesize = 8; 358 /* LCOV_EXCL_STOP */ 359 } 360 size += sizesize; 361 362 TEMP_ALLOC(buffer, size); 363 buffer[0] = 0x03; 364 if (sgn > 0) 365 buffer[1] = 0x01 | large; 366 else 367 buffer[1] = 0x02 | large; 368 369 /* Copy sizenum to the buffer. */ 370 sizetemp = sizenum; 371 for (i=0; i<sizesize; i++) { 372 buffer[i+2] = (char)(sizetemp & 0xff); 373 sizetemp >>= 8; 374 } 375 376 mpz_export(buffer+sizesize+2, &count, -1, 377 sizeof(char), 0, 0, mpq_numref(self->q)); 378 if (count != sizenum) { 379 /* LCOV_EXCL_START */ 380 SYSTEM_ERROR("internal error in Pympq_To_Binary"); 381 TEMP_FREE(buffer, size); 382 return NULL; 383 /* LCOV_EXCL_STOP */ 384 } 385 count = 0; 386 mpz_export(buffer+sizenum+sizesize+2, &count, -1, 387 sizeof(char), 0, 0, mpq_denref(self->q)); 388 if (count != sizeden) { 389 /* LCOV_EXCL_START */ 390 SYSTEM_ERROR("internal error in Pympq_To_Binary"); 391 TEMP_FREE(buffer, size); 392 return NULL; 393 /* LCOV_EXCL_STOP */ 394 } 395 396 397 done: 398 result = PyBytes_FromStringAndSize(buffer, size); 399 TEMP_FREE(buffer, size); 400 return result; 401 } 402 403 /* Format of the binary representation of an mpfr. 404 * 405 * byte[0]: 1 => mpz (see Pympz_To_Binary) 406 * 2 => xmpz (see Pyxmpz_To_Binary) 407 * 3 => mpq (see Pympq_To_Binary) 408 * 4 => mpfr 409 * 5 => mpc (see Pympc_To_Binary) 410 * byte[1:0]: 0 => value is "special" 411 * 1 => value is an actual number 412 * byte[1:1]: 0 => signbit is clear 413 * 1 => signbit is set 414 * byte[1:2-2]: 0 => 32-bit lengths (n=4) 415 * 1 => 64-bit lengths (n=8) 416 * byte[1:3-4]: 0 => 0 (see signbit) 417 * 1 => value is NaN 418 * 2 => value is Inf (see signbit) 419 * 3 => unassigned 420 * byte[1:5]: 0 => exponent is positive 421 * 1 => exponent is negative 422 * byte[1:6]: 0 => 4 byte limbs 423 * 1 => 8 byte limbs 424 * byte[2]: 0 => rc = 0 425 * 1 => rc > 0 426 * 2 => rc < 0 427 * byte[3]: mpfr.round_mode 428 * byte[4]+: precision, saved in 4 or 8 bytes 429 * byte[4+n]+: exponent, saved in 4 or 8 bytes 430 * byte[4+2n]+: mantissa 431 */ 432 433 static PyObject * 434 GMPy_MPFR_To_Binary(MPFR_Object *self) 435 { 436 size_t sizemant = 0, sizesize = 4, size = 4, sizetemp, i; 437 mp_limb_t templimb; 438 mpfr_prec_t precision; 439 mpfr_exp_t exponent = 0; 440 int sgn; 441 char *buffer, *cp, large = 0x00, expsgn = 0x00; 442 PyObject *result = 0; 443 444 /* Check if the precision, exponent and mantissa length can fit in 445 * 32 bits. 446 */ 447 448 sgn = mpfr_signbit(self->f); 449 precision = mpfr_get_prec(self->f); 450 451 /* Exponent and mantiss are only valid for regular numbers 452 * (not 0, Nan, Inf, -Inf). 453 */ 454 if (mpfr_regular_p(self->f)) { 455 exponent = self->f->_mpfr_exp; 456 if (exponent < 0) { 457 exponent = -exponent; 458 expsgn = 0x20; 459 } 460 /* Calculate the size of mantissa in limbs */ 461 sizemant = (self->f->_mpfr_prec + mp_bits_per_limb - 1)/mp_bits_per_limb; 462 } 463 if (((exponent >> 16) >> 16) || 464 ((precision >> 16) >> 16) || 465 ((sizemant >> 16) >> 16)) { 466 /* This can only be tested on 64-bit platforms. lcov will report the 467 * code as not tested until 64-bit specific tests are created. 468 */ 469 sizesize = 8; 470 large = 0x04; 471 } 472 473 if (!mpfr_regular_p(self->f)) { 474 /* Only need to save the precision. */ 475 size += sizesize; 476 TEMP_ALLOC(buffer, size); 477 buffer[0] = 0x04; 478 479 /* Set to all 0 since we are special. */ 480 buffer[1] = 0x00; 481 482 /* Set the sign bit. */ 483 if (sgn) buffer[1] |= 0x02; 484 485 /* 4 or 8 byte values. */ 486 buffer[1] |= large; 487 488 /* Check if NaN. */ 489 if (mpfr_nan_p(self->f)) buffer[1] |= 0x08; 490 491 /* Check if Infinity. */ 492 if (mpfr_inf_p(self->f)) buffer[1] |= 0x10; 493 494 /* Save the result code */ 495 if (self->rc == 0) buffer[2] = 0x00; 496 else if (self->rc > 0) buffer[2] = 0x01; 497 else buffer[2] = 0x02; 498 499 /* Save the precision */ 500 sizetemp = precision; 501 for (i=0; i<sizesize; i++) { 502 buffer[i+4] = (char)(sizetemp & 0xff); 503 sizetemp >>= 8; 504 } 505 goto done; 506 } 507 508 /* Now process all actual numbers. */ 509 size += (2 * sizesize) + (sizemant * (mp_bits_per_limb >> 3)); 510 TEMP_ALLOC(buffer, size); 511 buffer[0] = 0x04; 512 513 /* Set bit 0 to 1 since we are an actual number. */ 514 buffer[1] = 0x01; 515 516 /* Save the sign bit. */ 517 if (sgn) buffer[1] |= 0x02; 518 519 /* Save the size of the values. */ 520 buffer[1] |= large; 521 522 /* Save the exponent sign. */ 523 buffer[1] |= expsgn; 524 525 /* Save the limb size. */ 526 if ((mp_bits_per_limb >> 3) == 8) 527 buffer[1] |= 0x40; 528 /* This branch can only be reached on 32-bit platforms. */ 529 else if ((mp_bits_per_limb >> 3) != 4) { 530 /* LCOV_EXCL_START */ 531 SYSTEM_ERROR("cannot support current limb size"); 532 TEMP_FREE(buffer, size); 533 return NULL; 534 /* LCOV_EXCL_STOP */ 535 } 536 537 /* Save the result code. */ 538 if (self->rc == 0) buffer[2] = 0x00; 539 else if (self->rc > 0) buffer[2] = 0x01; 540 else buffer[2] = 0x02; 541 542 /* Rounding mode is no longer used, so just store a null byte. */ 543 buffer[3] = 0x00; 544 545 /* Save the precision */ 546 cp = buffer + 4; 547 sizetemp = precision; 548 for (i=0; i<sizesize; i++) { 549 cp[i] = (char)(sizetemp & 0xff); 550 sizetemp >>= 8; 551 } 552 553 /* Save the exponenet */ 554 cp += sizesize; 555 sizetemp = exponent; 556 for (i=0; i<sizesize; i++) { 557 cp[i] = (char)(sizetemp & 0xff); 558 sizetemp >>= 8; 559 } 560 561 /* Save the actual mantissa */ 562 cp += sizesize; 563 for (i=0; i<sizemant; i++) { 564 templimb = self->f->_mpfr_d[i]; 565 #if GMP_LIMB_BITS == 64 566 cp[0] = (char)(templimb & 0xff); 567 templimb >>= 8; 568 cp[1] = (char)(templimb & 0xff); 569 templimb >>= 8; 570 cp[2] = (char)(templimb & 0xff); 571 templimb >>= 8; 572 cp[3] = (char)(templimb & 0xff); 573 templimb >>= 8; 574 cp[4] = (char)(templimb & 0xff); 575 templimb >>= 8; 576 cp[5] = (char)(templimb & 0xff); 577 templimb >>= 8; 578 cp[6] = (char)(templimb & 0xff); 579 templimb >>= 8; 580 cp[7] = (char)(templimb & 0xff); 581 cp += 8; 582 #endif 583 #if GMP_LIMB_BITS == 32 584 cp[0] = (char)(templimb & 0xff); 585 templimb >>= 8; 586 cp[1] = (char)(templimb & 0xff); 587 templimb >>= 8; 588 cp[2] = (char)(templimb & 0xff); 589 templimb >>= 8; 590 cp[3] = (char)(templimb & 0xff); 591 cp += 4; 592 #endif 593 } 594 595 done: 596 result = PyBytes_FromStringAndSize(buffer, size); 597 TEMP_FREE(buffer, size); 598 return result; 599 } 600 601 /* Format of the binary representation of an mpc. 602 * 603 * The format consists of the concatenation of mpfrs (real and imaginary) 604 * converted to binary format. The 0x04 leading byte of each binary string 605 * is replaced by 0x05. 606 */ 607 608 static PyObject * 609 GMPy_MPC_To_Binary(MPC_Object *obj) 610 { 611 MPFR_Object *real = NULL, *imag = NULL; 612 PyObject *result = NULL, *temp = NULL; 613 mpfr_prec_t rprec = 0, iprec = 0; 614 CTXT_Object *context = NULL; 615 616 CHECK_CONTEXT(context); 617 618 mpc_get_prec2(&rprec, &iprec, obj->c); 619 620 if (!(real = GMPy_MPFR_New(rprec, context)) || 621 !(imag = GMPy_MPFR_New(iprec, context))) { 622 /* LCOV_EXCL_START */ 623 Py_XDECREF((PyObject*)real); 624 Py_XDECREF((PyObject*)imag); 625 return NULL; 626 /* LCOV_EXCL_STOP */ 627 } 628 629 mpfr_set(real->f, mpc_realref(obj->c), MPFR_RNDN); 630 mpfr_set(imag->f, mpc_imagref(obj->c), MPFR_RNDN); 631 real->rc = obj->rc; 632 633 if (!(result = GMPy_MPFR_To_Binary(real)) || 634 !(temp = GMPy_MPFR_To_Binary(imag))) { 635 /* LCOV_EXCL_START */ 636 Py_XDECREF((PyObject*)result); 637 Py_XDECREF((PyObject*)temp); 638 Py_DECREF((PyObject*)real); 639 Py_DECREF((PyObject*)imag); 640 return NULL; 641 /* LCOV_EXCL_STOP */ 642 } 643 644 Py_DECREF((PyObject*)real); 645 Py_DECREF((PyObject*)imag); 646 647 PyBytes_AS_STRING(result)[0] = 0x05; 648 PyBytes_AS_STRING(temp)[0] = 0x05; 649 650 PyBytes_ConcatAndDel(&result, temp); 651 return result; 652 } 653 654 PyDoc_STRVAR(doc_from_binary, 655 "from_binary(bytes) -> gmpy2 object\n" 656 "Return a Python object from a byte sequence created by\n" 657 "gmpy2.to_binary()."); 658 659 660 static PyObject * 661 GMPy_MPANY_From_Binary(PyObject *self, PyObject *other) 662 { 663 unsigned char *buffer, *cp; 664 Py_ssize_t len; 665 CTXT_Object *context = NULL; 666 667 CHECK_CONTEXT(context); 668 669 if (!(PyBytes_Check(other))) { 670 TYPE_ERROR("from_binary() requires bytes argument"); 671 return NULL; 672 } 673 674 len = PyBytes_Size(other); 675 if (len < 2) { 676 VALUE_ERROR("byte sequence too short for from_binary()"); 677 return NULL; 678 } 679 buffer = (unsigned char*)PyBytes_AsString(other); 680 cp = buffer; 681 682 switch (cp[0]) { 683 case 0x01: { 684 MPZ_Object *result; 685 686 if (!(result = GMPy_MPZ_New(NULL))) { 687 /* LCOV_EXCL_START */ 688 return NULL; 689 /* LCOV_EXCL_STOP */ 690 } 691 if (cp[1] == 0x00) { 692 mpz_set_ui(result->z, 0); 693 return (PyObject*)result; 694 } 695 mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2); 696 if (cp[1] == 0x02) 697 mpz_neg(result->z, result->z); 698 return (PyObject*)result; 699 break; 700 } 701 case 0x02: { 702 XMPZ_Object *result; 703 704 if (!(result = GMPy_XMPZ_New(NULL))) { 705 /* LCOV_EXCL_START */ 706 return NULL; 707 /* LCOV_EXCL_STOP */ 708 } 709 if (cp[1] == 0x00) { 710 mpz_set_ui(result->z, 0); 711 return (PyObject*)result; 712 } 713 mpz_import(result->z, len-2, -1, sizeof(char), 0, 0, cp+2); 714 if (cp[1] == 0x02) 715 mpz_neg(result->z, result->z); 716 return (PyObject*)result; 717 break; 718 } 719 case 0x03: { 720 MPQ_Object *result; 721 Py_ssize_t numlen = 0, sizesize = 4, i; 722 mpz_t num, den; 723 724 if (!(result = GMPy_MPQ_New(NULL))) { 725 /* LCOV_EXCL_START */ 726 return NULL; 727 /* LCOV_EXCL_STOP */ 728 } 729 if (cp[1] == 0x00) { 730 mpq_set_ui(result->q, 0, 1); 731 return (PyObject*)result; 732 } 733 if (cp[1] & 0x04) 734 sizesize = 8; 735 736 if (len < 2 + sizesize) { 737 VALUE_ERROR("byte sequence too short for from_binary()"); 738 return NULL; 739 } 740 741 for (i=sizesize; i>0; --i) { 742 numlen = (numlen << 8) + cp[i+1]; 743 } 744 745 if (len < 2 + sizesize + numlen + 1) { 746 VALUE_ERROR("byte sequence too short for from_binary()"); 747 return NULL; 748 } 749 750 mpz_init(num); 751 mpz_init(den); 752 mpz_import(num, numlen, -1, 753 sizeof(char), 0, 0, cp+sizesize+2); 754 mpz_import(den, len-numlen-sizesize-2, -1, 755 sizeof(char), 0, 0, cp+sizesize+numlen+2); 756 mpq_set_num(result->q, num); 757 mpq_set_den(result->q, den); 758 mpq_canonicalize(result->q); 759 mpz_clear(num); 760 mpz_clear(den); 761 762 if (cp[1] == 0x02) 763 mpq_neg(result->q, result->q); 764 return (PyObject*)result; 765 break; 766 } 767 case 0x04: { 768 MPFR_Object *result; 769 Py_ssize_t sizemant = 0, sizesize = 4, i, newmant; 770 mpfr_prec_t precision = 0; 771 mpfr_exp_t exponent = 0; 772 mp_limb_t templimb; 773 int sgn = 1, expsgn = 1, limbsize = 4; 774 int newlimbsize = (mp_bits_per_limb >> 3); 775 776 if (len < 4) { 777 VALUE_ERROR("byte sequence too short for from_binary()"); 778 return NULL; 779 } 780 781 /* Get size of values. */ 782 if (cp[1] & 0x04) sizesize = 8; 783 784 /* Get the original precision. */ 785 for (i=sizesize; i>0; --i) { 786 precision = (precision << 8) + cp[i+3]; 787 } 788 789 /* Get the original sign bit. */ 790 if (cp[1] & 0x02) sgn = -1; 791 792 /* Get the original exponent sign. */ 793 if (cp[1] & 0x20) expsgn = -1; 794 795 /* Get the limb size of the originating system. */ 796 if (cp[1] & 0x40) limbsize = 8; 797 798 799 if (!(result = GMPy_MPFR_New(precision, context))) { 800 /* LCOV_EXCL_START */ 801 return NULL; 802 /* LCOV_EXCL_STOP */ 803 } 804 805 /* Restore the original result code and rounding mode. */ 806 807 /* Get the original result code. */ 808 if (cp[2] == 0) result->rc = 0; 809 else if (cp[2] == 1) result->rc = 1; 810 else result->rc = -1; 811 812 if (!(cp[1] & 0x01)) { 813 /* Process special numbers. */ 814 if ((cp[1] & 0x18) == 0x00) 815 mpfr_set_zero(result->f, sgn); 816 else if ((cp[1] & 0x18) == 0x08) 817 mpfr_set_nan(result->f); 818 else 819 mpfr_set_inf(result->f, sgn); 820 return (PyObject*)result; 821 } 822 /* Process actual numbers. */ 823 824 /* Calculate the number of limbs on the original system. */ 825 if (limbsize == 8) sizemant = ((precision + 63) / 64); 826 else sizemant = ((precision + 31) / 32); 827 828 /* Calculate the number of limbs on the current system. */ 829 newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; 830 831 /* Get the original exponent. */ 832 cp = buffer + 4 + sizesize - 1; 833 for (i=sizesize; i>0; --i) { 834 exponent = (exponent << 8) + cp[i]; 835 } 836 837 if (len < 2 + sizesize) { 838 VALUE_ERROR("byte sequence too short for from_binary()"); 839 return NULL; 840 } 841 842 /* Check if the mantissa occupies the same number of bytes 843 * on both the source and target system. */ 844 if (limbsize * sizemant == newmant * newlimbsize) { 845 mpfr_set_ui(result->f, 1, MPFR_RNDN); 846 cp = buffer + 4 + (2 * sizesize); 847 for (i=0; i<newmant; i++) { 848 #if GMP_LIMB_BITS == 64 849 templimb = cp[7]; 850 templimb = (templimb << 8) + cp[6]; 851 templimb = (templimb << 8) + cp[5]; 852 templimb = (templimb << 8) + cp[4]; 853 templimb = (templimb << 8) + cp[3]; 854 templimb = (templimb << 8) + cp[2]; 855 templimb = (templimb << 8) + cp[1]; 856 templimb = (templimb << 8) + cp[0]; 857 #endif 858 #if GMP_LIMB_BITS == 32 859 templimb = cp[3]; 860 templimb = (templimb << 8) + cp[2]; 861 templimb = (templimb << 8) + cp[1]; 862 templimb = (templimb << 8) + cp[0]; 863 #endif 864 result->f->_mpfr_d[i] = templimb; 865 cp += newlimbsize; 866 } 867 result->f->_mpfr_exp = expsgn * exponent; 868 if (sgn == -1) 869 mpfr_neg(result->f, result->f, MPFR_RNDN); 870 return (PyObject*)result; 871 } 872 else if (limbsize * sizemant > newmant * newlimbsize) { 873 /* Since the amount of saved data is greater than the amount of 874 * data needed on the new system, we skip the first 32 bits 875 * since they must be 0. 876 */ 877 878 /* Verify we are on a 32-bit system and the source was 64-bit. */ 879 if ((limbsize == 8) && (newlimbsize == 4)) { 880 VALUE_ERROR("byte sequence invalid for from_binary()"); 881 return NULL; 882 } 883 884 mpfr_set_ui(result->f, 1, MPFR_RNDN); 885 cp = buffer + 4 + (2 * sizesize) + 4; 886 for (i=0; i<newmant; i++) { 887 templimb = cp[3]; 888 templimb = (templimb << 8) + cp[2]; 889 templimb = (templimb << 8) + cp[1]; 890 templimb = (templimb << 8) + cp[0]; 891 result->f->_mpfr_d[i] = templimb; 892 cp += newlimbsize; 893 } 894 result->f->_mpfr_exp = expsgn * exponent; 895 if (sgn == -1) 896 mpfr_neg(result->f, result->f, MPFR_RNDN); 897 return (PyObject*)result; 898 } 899 else { 900 /* Since the amount of saved data is less than the amount of 901 * data needed on the new system, we must "add" 32 0-bits at 902 * the low end. 903 */ 904 905 /* Verify we are on a 64-bit system and the source was 32-bit. */ 906 if ((limbsize == 4) && (newlimbsize == 8)) { 907 VALUE_ERROR("byte sequence invalid for from_binary()"); 908 return NULL; 909 } 910 911 mpfr_set_ui(result->f, 1, MPFR_RNDN); 912 cp = buffer + 4 + (2 * sizesize); 913 templimb = cp[3]; 914 templimb = (templimb << 8) + cp[2]; 915 templimb = (templimb << 8) + cp[1]; 916 templimb = (templimb << 8) + cp[0]; 917 result->f->_mpfr_d[i] = ((templimb << 16) << 16); 918 cp += 4; 919 for (i=0; i<newmant-1; i++) { 920 templimb = cp[7]; 921 templimb = (templimb << 8) + cp[6]; 922 templimb = (templimb << 8) + cp[5]; 923 templimb = (templimb << 8) + cp[4]; 924 templimb = (templimb << 8) + cp[3]; 925 templimb = (templimb << 8) + cp[2]; 926 templimb = (templimb << 8) + cp[1]; 927 templimb = (templimb << 8) + cp[0]; 928 result->f->_mpfr_d[i] = templimb; 929 cp += newlimbsize; 930 } 931 result->f->_mpfr_exp = expsgn * exponent; 932 if (sgn == -1) 933 mpfr_neg(result->f, result->f, MPFR_RNDN); 934 return (PyObject*)result; 935 } 936 } 937 case 0x05: { 938 MPC_Object *result; 939 MPFR_Object *real = 0, *imag = 0; 940 Py_ssize_t sizemant = 0, sizesize = 4, i, newmant; 941 mpfr_prec_t precision = 0; 942 mpfr_exp_t exponent = 0; 943 mp_limb_t templimb; 944 int sgn = 1, expsgn = 1, limbsize = 4; 945 int newlimbsize = (mp_bits_per_limb >> 3); 946 unsigned char *tempbuf; 947 948 if (len < 4) { 949 VALUE_ERROR("byte sequence too short for from_binary()"); 950 return NULL; 951 } 952 /* read the real part first */ 953 if (cp[1] & 0x04) sizesize = 8; 954 for (i=sizesize; i>0; --i) { 955 precision = (precision << 8) + cp[i+3]; 956 } 957 if (cp[1] & 0x02) sgn = -1; 958 if (cp[1] & 0x20) expsgn = -1; 959 if (cp[1] & 0x40) limbsize = 8; 960 if (!(real = GMPy_MPFR_New(precision, context))) { 961 /* LCOV_EXCL_START */ 962 return NULL; 963 /* LCOV_EXCL_STOP */ 964 } 965 if (cp[2] == 0) real->rc = 0; 966 else if (cp[2] == 1) real->rc = 1; 967 else real->rc = -1; 968 if (!(cp[1] & 0x01)) { 969 if ((cp[1] & 0x18) == 0x00) 970 mpfr_set_zero(real->f, sgn); 971 else if ((cp[1] & 0x18) == 0x08) 972 mpfr_set_nan(real->f); 973 else 974 mpfr_set_inf(real->f, sgn); 975 cp += 4 + sizesize; 976 goto readimag; 977 } 978 if (limbsize == 8) sizemant = ((precision + 63) / 64); 979 else sizemant = ((precision + 31) / 32); 980 newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; 981 cp = buffer + 4 + sizesize - 1; 982 for (i=sizesize; i>0; --i) { 983 exponent = (exponent << 8) + cp[i]; 984 } 985 if (limbsize * sizemant == newmant * newlimbsize) { 986 mpfr_set_ui(real->f, 1, MPFR_RNDN); 987 cp = buffer + 4 + (2 * sizesize); 988 for (i=0; i<newmant; i++) { 989 #if GMP_LIMB_BITS == 64 990 templimb = cp[7]; 991 templimb = (templimb << 8) + cp[6]; 992 templimb = (templimb << 8) + cp[5]; 993 templimb = (templimb << 8) + cp[4]; 994 templimb = (templimb << 8) + cp[3]; 995 templimb = (templimb << 8) + cp[2]; 996 templimb = (templimb << 8) + cp[1]; 997 templimb = (templimb << 8) + cp[0]; 998 #endif 999 #if GMP_LIMB_BITS == 32 1000 templimb = cp[3]; 1001 templimb = (templimb << 8) + cp[2]; 1002 templimb = (templimb << 8) + cp[1]; 1003 templimb = (templimb << 8) + cp[0]; 1004 #endif 1005 real->f->_mpfr_d[i] = templimb; 1006 cp += newlimbsize; 1007 } 1008 real->f->_mpfr_exp = expsgn * exponent; 1009 if (sgn == -1) 1010 mpfr_neg(real->f, real->f, MPFR_RNDN); 1011 } 1012 else if (limbsize * sizemant > newmant * newlimbsize) { 1013 if ((limbsize == 8) && (newlimbsize == 4)) { 1014 VALUE_ERROR("byte sequence invalid for from_binary()"); 1015 Py_DECREF((PyObject*)real); 1016 return NULL; 1017 } 1018 mpfr_set_ui(real->f, 1, MPFR_RNDN); 1019 cp = buffer + 4 + (2 * sizesize) + 4; 1020 for (i=0; i<newmant; i++) { 1021 templimb = cp[3]; 1022 templimb = (templimb << 8) + cp[2]; 1023 templimb = (templimb << 8) + cp[1]; 1024 templimb = (templimb << 8) + cp[0]; 1025 real->f->_mpfr_d[i] = templimb; 1026 cp += newlimbsize; 1027 } 1028 real->f->_mpfr_exp = expsgn * exponent; 1029 if (sgn == -1) 1030 mpfr_neg(real->f, real->f, MPFR_RNDN); 1031 } 1032 else { 1033 if ((limbsize == 4) && (newlimbsize == 8)) { 1034 VALUE_ERROR("byte sequence invalid for from_binary()"); 1035 Py_DECREF((PyObject*)real); 1036 return NULL; 1037 } 1038 mpfr_set_ui(real->f, 1, MPFR_RNDN); 1039 cp = buffer + 4 + (2 * sizesize); 1040 templimb = cp[3]; 1041 templimb = (templimb << 8) + cp[2]; 1042 templimb = (templimb << 8) + cp[1]; 1043 templimb = (templimb << 8) + cp[0]; 1044 real->f->_mpfr_d[i] = ((templimb << 16) << 16); 1045 cp += 4; 1046 for (i=0; i<newmant-1; i++) { 1047 templimb = cp[7]; 1048 templimb = (templimb << 8) + cp[6]; 1049 templimb = (templimb << 8) + cp[5]; 1050 templimb = (templimb << 8) + cp[4]; 1051 templimb = (templimb << 8) + cp[3]; 1052 templimb = (templimb << 8) + cp[2]; 1053 templimb = (templimb << 8) + cp[1]; 1054 templimb = (templimb << 8) + cp[0]; 1055 real->f->_mpfr_d[i] = templimb; 1056 cp += newlimbsize; 1057 } 1058 real->f->_mpfr_exp = expsgn * exponent; 1059 if (sgn == -1) 1060 mpfr_neg(real->f, real->f, MPFR_RNDN); 1061 } 1062 readimag: 1063 /* Set all the variables back to default. */ 1064 tempbuf = cp; 1065 1066 sizemant = 0; 1067 sizesize = 4; 1068 precision = 0; 1069 exponent = 0; 1070 sgn = 1; 1071 expsgn = 1; 1072 limbsize = 4; 1073 1074 /* Done reading the real part. The next byte should be 0x05. */ 1075 if (!(cp[0] == 0x05)) { 1076 VALUE_ERROR("byte sequence invalid for from_binary()"); 1077 Py_DECREF((PyObject*)real); 1078 return NULL; 1079 } 1080 if (cp[1] & 0x04) sizesize = 8; 1081 for (i=sizesize; i>0; --i) { 1082 precision = (precision << 8) + cp[i+3]; 1083 } 1084 if (cp[1] & 0x02) sgn = -1; 1085 if (cp[1] & 0x20) expsgn = -1; 1086 if (cp[1] & 0x40) limbsize = 8; 1087 if (!(imag = GMPy_MPFR_New(precision, context))) { 1088 /* LCOV_EXCL_START */ 1089 Py_DECREF((PyObject*)real); 1090 return NULL; 1091 /* LCOV_EXCL_STOP */ 1092 } 1093 if (cp[2] == 0) imag->rc = 0; 1094 else if (cp[2] == 1) imag->rc = 1; 1095 else imag->rc = -1; 1096 if (!(cp[1] & 0x01)) { 1097 if ((cp[1] & 0x18) == 0x00) 1098 mpfr_set_zero(imag->f, sgn); 1099 else if ((cp[1] & 0x18) == 0x08) 1100 mpfr_set_nan(imag->f); 1101 else 1102 mpfr_set_inf(imag->f, sgn); 1103 goto alldone; 1104 } 1105 if (limbsize == 8) sizemant = ((precision + 63) / 64); 1106 else sizemant = ((precision + 31) / 32); 1107 newmant = (precision + mp_bits_per_limb - 1) / mp_bits_per_limb; 1108 cp = tempbuf + 4 + sizesize - 1; 1109 for (i=sizesize; i>0; --i) { 1110 exponent = (exponent << 8) + cp[i]; 1111 } 1112 if (limbsize * sizemant == newmant * newlimbsize) { 1113 mpfr_set_ui(imag->f, 1, MPFR_RNDN); 1114 cp = tempbuf + 4 + (2 * sizesize); 1115 for (i=0; i<newmant; i++) { 1116 #if GMP_LIMB_BITS == 64 1117 templimb = cp[7]; 1118 templimb = (templimb << 8) + cp[6]; 1119 templimb = (templimb << 8) + cp[5]; 1120 templimb = (templimb << 8) + cp[4]; 1121 templimb = (templimb << 8) + cp[3]; 1122 templimb = (templimb << 8) + cp[2]; 1123 templimb = (templimb << 8) + cp[1]; 1124 templimb = (templimb << 8) + cp[0]; 1125 #endif 1126 #if GMP_LIMB_BITS == 32 1127 templimb = cp[3]; 1128 templimb = (templimb << 8) + cp[2]; 1129 templimb = (templimb << 8) + cp[1]; 1130 templimb = (templimb << 8) + cp[0]; 1131 #endif 1132 imag->f->_mpfr_d[i] = templimb; 1133 cp += newlimbsize; 1134 } 1135 imag->f->_mpfr_exp = expsgn * exponent; 1136 if (sgn == -1) 1137 mpfr_neg(imag->f, imag->f, MPFR_RNDN); 1138 } 1139 else if (limbsize * sizemant > newmant * newlimbsize) { 1140 if ((limbsize == 8) && (newlimbsize == 4)) { 1141 VALUE_ERROR("byte sequence invalid for from_binary()"); 1142 Py_DECREF((PyObject*)real); 1143 Py_DECREF((PyObject*)imag); 1144 return NULL; 1145 } 1146 mpfr_set_ui(imag->f, 1, MPFR_RNDN); 1147 cp = tempbuf + 4 + (2 * sizesize) + 4; 1148 for (i=0; i<newmant; i++) { 1149 templimb = cp[3]; 1150 templimb = (templimb << 8) + cp[2]; 1151 templimb = (templimb << 8) + cp[1]; 1152 templimb = (templimb << 8) + cp[0]; 1153 imag->f->_mpfr_d[i] = templimb; 1154 cp += newlimbsize; 1155 } 1156 imag->f->_mpfr_exp = expsgn * exponent; 1157 if (sgn == -1) 1158 mpfr_neg(imag->f, imag->f, MPFR_RNDN); 1159 } 1160 else { 1161 if ((limbsize == 4) && (newlimbsize == 8)) { 1162 VALUE_ERROR("byte sequence invalid for from_binary()"); 1163 Py_DECREF((PyObject*)real); 1164 Py_DECREF((PyObject*)imag); 1165 return NULL; 1166 } 1167 mpfr_set_ui(imag->f, 1, MPFR_RNDN); 1168 cp = tempbuf + 4 + (2 * sizesize); 1169 templimb = cp[3]; 1170 templimb = (templimb << 8) + cp[2]; 1171 templimb = (templimb << 8) + cp[1]; 1172 templimb = (templimb << 8) + cp[0]; 1173 imag->f->_mpfr_d[i] = ((templimb << 16) << 16); 1174 cp += 4; 1175 for (i=0; i<newmant-1; i++) { 1176 templimb = cp[7]; 1177 templimb = (templimb << 8) + cp[6]; 1178 templimb = (templimb << 8) + cp[5]; 1179 templimb = (templimb << 8) + cp[4]; 1180 templimb = (templimb << 8) + cp[3]; 1181 templimb = (templimb << 8) + cp[2]; 1182 templimb = (templimb << 8) + cp[1]; 1183 templimb = (templimb << 8) + cp[0]; 1184 imag->f->_mpfr_d[i] = templimb; 1185 cp += newlimbsize; 1186 } 1187 imag->f->_mpfr_exp = expsgn * exponent; 1188 if (sgn == -1) 1189 mpfr_neg(imag->f, imag->f, MPFR_RNDN); 1190 } 1191 alldone: 1192 if (!(result = (MPC_Object*)GMPy_MPC_New(0, 0, context))) { 1193 /* LCOV_EXCL_START */ 1194 Py_DECREF((PyObject*)real); 1195 Py_DECREF((PyObject*)imag); 1196 return NULL; 1197 /* LCOV_EXCL_STOP */ 1198 } 1199 mpfr_swap(mpc_realref(result->c), real->f); 1200 mpfr_swap(mpc_imagref(result->c), imag->f); 1201 Py_DECREF((PyObject*)real); 1202 Py_DECREF((PyObject*)imag); 1203 return (PyObject*)result; 1204 } 1205 default: { 1206 TYPE_ERROR("from_binary() argument type not supported"); 1207 return NULL; 1208 } 1209 } 1210 } 1211 1212 PyDoc_STRVAR(doc_to_binary, 1213 "to_binary(x) -> bytes\n" 1214 "Return a Python byte sequence that is a portable binary\n" 1215 "representation of a gmpy2 object x. The byte sequence can\n" 1216 "be passed to gmpy2.from_binary() to obtain an exact copy of\n" 1217 "x's value. Works with mpz, xmpz, mpq, mpfr, and mpc types. \n" 1218 "Raises TypeError if x is not a gmpy2 object."); 1219 1220 static PyObject * 1221 GMPy_MPANY_To_Binary(PyObject *self, PyObject *other) 1222 { 1223 if(MPZ_Check(other)) 1224 return GMPy_MPZ_To_Binary((MPZ_Object*)other); 1225 else if(XMPZ_Check(other)) 1226 return GMPy_XMPZ_To_Binary((XMPZ_Object*)other); 1227 else if(MPQ_Check(other)) 1228 return GMPy_MPQ_To_Binary((MPQ_Object*)other); 1229 else if(MPFR_Check(other)) 1230 return GMPy_MPFR_To_Binary((MPFR_Object*)other); 1231 else if(MPC_Check(other)) 1232 return GMPy_MPC_To_Binary((MPC_Object*)other); 1233 TYPE_ERROR("to_binary() argument type not supported"); 1234 return NULL; 1235 } 1236