PageRenderTime 84ms CodeModel.GetById 13ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 1ms

/src/gmpy_binary.c

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