PageRenderTime 75ms CodeModel.GetById 12ms app.highlight 58ms RepoModel.GetById 1ms app.codeStats 0ms

/src/gmpy_mpz_divmod2exp.c

http://gmpy.googlecode.com/
C | 644 lines | 504 code | 85 blank | 55 comment | 118 complexity | 5aa4600ffc3a29ec6b73f4fa20b2bdc7 MD5 | raw file
  1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2 * gmpy_mpz_divmod2exp.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
 29/* This file contains functions related to division and remainder by a power
 30 * of two.
 31 */
 32
 33/*
 34 **************************************************************************
 35 * Ceiling division and remainder by power of two.
 36 **************************************************************************
 37 */
 38
 39PyDoc_STRVAR(doc_gmpy_c_divmod_2exp,
 40"c_divmod_2exp(x ,n) -> (quotient, remainder)\n\n"
 41"Return the quotient and remainder of x divided by 2**n. The quotient\n"
 42"is rounded towards +Inf (ceiling rounding) and the remainder will\n"
 43"be negative. x must be an integer. n must be >0.");
 44
 45static PyObject *
 46Pygmpy_c_divmod_2exp(PyObject *self, PyObject *args)
 47{
 48    mp_bitcnt_t nbits;
 49    PyObject *x, *result;
 50    PympzObject *q, *r, *tempx;
 51
 52    if (PyTuple_GET_SIZE(args) != 2) {
 53        TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments");
 54        return NULL;
 55    }
 56
 57    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
 58    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
 59        return NULL;
 60    }
 61
 62    x = PyTuple_GET_ITEM(args, 0);
 63    CREATE_TWO_MPZ_TUPLE(q, r, result);
 64
 65    if (CHECK_MPZANY(x)) {
 66        mpz_cdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits);
 67        mpz_cdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits);
 68    }
 69    else {
 70        if (!(tempx = Pympz_From_Integer(x))) {
 71            TYPE_ERROR("c_divmod_2exp() requires 'mpz','int' arguments");
 72            Py_DECREF((PyObject*)q);
 73            Py_DECREF((PyObject*)r);
 74            Py_DECREF(result);
 75            return NULL;
 76        }
 77        mpz_cdiv_q_2exp(q->z, tempx->z, nbits);
 78        mpz_cdiv_r_2exp(r->z, tempx->z, nbits);
 79        Py_DECREF((PyObject*)tempx);
 80    }
 81    PyTuple_SET_ITEM(result, 0, (PyObject*)q);
 82    PyTuple_SET_ITEM(result, 1, (PyObject*)r);
 83    return result;
 84}
 85
 86PyDoc_STRVAR(doc_gmpy_c_div_2exp,
 87"c_div_2exp(x, n) -> quotient\n\n"
 88"Returns the quotient of x divided by 2**n. The quotient is rounded\n"
 89"towards +Inf (ceiling rounding). x must be an integer. n must be >0.");
 90
 91static PyObject *
 92Pygmpy_c_div_2exp(PyObject *self, PyObject *args)
 93{
 94    mp_bitcnt_t nbits;
 95    PyObject *x;
 96    PympzObject *result, *tempx;
 97
 98    if (PyTuple_GET_SIZE(args) != 2) {
 99        TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments");
100        return NULL;
101    }
102
103    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
104    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
105        return NULL;
106    }
107
108    x = PyTuple_GET_ITEM(args, 0);
109    if (!(result = (PympzObject*)Pympz_new()))
110        return NULL;
111
112    if (CHECK_MPZANY(x)) {
113        mpz_cdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits);
114    }
115    else {
116        if (!(tempx = Pympz_From_Integer(x))) {
117            TYPE_ERROR("c_div_2exp() requires 'mpz','int' arguments");
118            Py_DECREF((PyObject*)result);
119            return NULL;
120        }
121        mpz_cdiv_q_2exp(result->z, tempx->z, nbits);
122        Py_DECREF((PyObject*)tempx);
123    }
124    return (PyObject*)result;
125}
126
127PyDoc_STRVAR(doc_gmpy_c_mod_2exp,
128"c_mod_2exp(x, n) -> remainder\n\n"
129"Return the remainder of x divided by 2**n. The remainder will be\n"
130"negative. x must be an integer. n must be >0.");
131
132static PyObject *
133Pygmpy_c_mod_2exp(PyObject *self, PyObject *args)
134{
135    mp_bitcnt_t nbits;
136    PyObject *x;
137    PympzObject *result, *tempx;
138
139    if (PyTuple_GET_SIZE(args) != 2) {
140        TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments");
141        return NULL;
142    }
143
144    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
145    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
146        return NULL;
147    }
148
149    x = PyTuple_GET_ITEM(args, 0);
150    if (!(result = (PympzObject*)Pympz_new()))
151        return NULL;
152
153    if (CHECK_MPZANY(x)) {
154        mpz_cdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits);
155    }
156    else {
157        if (!(tempx = Pympz_From_Integer(x))) {
158            TYPE_ERROR("c_mod_2exp() requires 'mpz','int' arguments");
159            Py_DECREF((PyObject*)result);
160            return NULL;
161        }
162        mpz_cdiv_r_2exp(result->z, tempx->z, nbits);
163        Py_DECREF((PyObject*)tempx);
164    }
165    return (PyObject*)result;
166}
167
168/*
169 **************************************************************************
170 * Floor division and remainder by power of two.
171 **************************************************************************
172 */
173
174PyDoc_STRVAR(doc_gmpy_f_divmod_2exp,
175"f_divmod_2exp(x, n) -> (quotient, remainder)\n\n"
176"Return quotient and remainder after dividing x by 2**n. The quotient\n"
177"is rounded towards -Inf (floor rounding) and the remainder will be\n"
178"positive. x must be an integer. n must be >0.");
179
180static PyObject *
181Pygmpy_f_divmod_2exp(PyObject *self, PyObject *args)
182{
183    mp_bitcnt_t nbits;
184    PyObject *x, *result;
185    PympzObject *q, *r, *tempx;
186
187    if (PyTuple_GET_SIZE(args) != 2) {
188        TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments");
189        return NULL;
190    }
191
192    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
193    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
194        return NULL;
195    }
196
197    x = PyTuple_GET_ITEM(args, 0);
198    CREATE_TWO_MPZ_TUPLE(q, r, result);
199
200    if (CHECK_MPZANY(x)) {
201        mpz_fdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits);
202        mpz_fdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits);
203    }
204    else {
205        if (!(tempx = Pympz_From_Integer(x))) {
206            TYPE_ERROR("f_divmod_2exp() requires 'mpz','int' arguments");
207            Py_DECREF((PyObject*)q);
208            Py_DECREF((PyObject*)r);
209            Py_DECREF(result);
210            return NULL;
211        }
212        mpz_fdiv_q_2exp(q->z, tempx->z, nbits);
213        mpz_fdiv_r_2exp(r->z, tempx->z, nbits);
214        Py_DECREF((PyObject*)tempx);
215    }
216    PyTuple_SET_ITEM(result, 0, (PyObject*)q);
217    PyTuple_SET_ITEM(result, 1, (PyObject*)r);
218    return result;
219}
220
221PyDoc_STRVAR(doc_gmpy_f_div_2exp,
222"f_div_2exp(x, n) -? quotient\n\n"
223"Return the quotient of x divided by 2**n. The quotient is rounded\n"
224"towards -Inf (floor rounding). x must be an integer. n must be >0.");
225
226static PyObject *
227Pygmpy_f_div_2exp(PyObject *self, PyObject *args)
228{
229    mp_bitcnt_t nbits;
230    PyObject *x;
231    PympzObject *result, *tempx;
232
233    if (PyTuple_GET_SIZE(args) != 2) {
234        TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments");
235        return NULL;
236    }
237
238    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
239    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
240        return NULL;
241    }
242
243    x = PyTuple_GET_ITEM(args, 0);
244    if (!(result = (PympzObject*)Pympz_new()))
245        return NULL;
246
247    if (CHECK_MPZANY(x)) {
248        mpz_fdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits);
249    }
250    else {
251        if (!(tempx = Pympz_From_Integer(x))) {
252            TYPE_ERROR("f_div_2exp() requires 'mpz','int' arguments");
253            Py_DECREF((PyObject*)result);
254            return NULL;
255        }
256        mpz_fdiv_q_2exp(result->z, tempx->z, nbits);
257        Py_DECREF((PyObject*)tempx);
258    }
259    return (PyObject*)result;
260}
261
262PyDoc_STRVAR(doc_gmpy_f_mod_2exp,
263"f_mod_2exp(x, n) -> remainder\n\n"
264"Return remainder of x divided by 2**n. The remainder will be\n"
265"positive. x must be an integer. n must be >0.");
266
267static PyObject *
268Pygmpy_f_mod_2exp(PyObject *self, PyObject *args)
269{
270    mp_bitcnt_t nbits;
271    PyObject *x;
272    PympzObject *result, *tempx;
273
274    if (PyTuple_GET_SIZE(args) != 2) {
275        TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments");
276        return NULL;
277    }
278
279    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
280    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
281        return NULL;
282    }
283
284    x = PyTuple_GET_ITEM(args, 0);
285    if (!(result = (PympzObject*)Pympz_new()))
286        return NULL;
287
288    if (CHECK_MPZANY(x)) {
289        mpz_fdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits);
290    }
291    else {
292        if (!(tempx = Pympz_From_Integer(x))) {
293            TYPE_ERROR("f_mod_2exp() requires 'mpz','int' arguments");
294            Py_DECREF((PyObject*)result);
295            return NULL;
296        }
297        mpz_fdiv_r_2exp(result->z, Pympz_AS_MPZ(tempx), nbits);
298        Py_DECREF((PyObject*)tempx);
299    }
300    return (PyObject*)result;
301}
302
303/*
304 **************************************************************************
305 * Truncating division and remainder by power of two.
306 **************************************************************************
307 */
308
309PyDoc_STRVAR(doc_gmpy_t_divmod_2exp,
310"t_divmod_2exp(x, n) -> (quotient, remaidner)\n\n"
311"Return the quotient and remainder of x divided by 2**n. The quotient\n"
312"is rounded towards zero (truncation) and the remainder will have the\n"
313"same sign as x. x must be an integer. n must be >0.");
314
315static PyObject *
316Pygmpy_t_divmod_2exp(PyObject *self, PyObject *args)
317{
318    mp_bitcnt_t nbits;
319    PyObject *x, *result;
320    PympzObject *q, *r, *tempx;
321
322    if (PyTuple_GET_SIZE(args) != 2) {
323        TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments");
324        return NULL;
325    }
326
327    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
328    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
329        return NULL;
330    }
331
332    x = PyTuple_GET_ITEM(args, 0);
333    CREATE_TWO_MPZ_TUPLE(q, r, result);
334
335    if (CHECK_MPZANY(x)) {
336        mpz_tdiv_q_2exp(q->z, Pympz_AS_MPZ(x), nbits);
337        mpz_tdiv_r_2exp(r->z, Pympz_AS_MPZ(x), nbits);
338    }
339    else {
340        if (!(tempx = Pympz_From_Integer(x))) {
341            TYPE_ERROR("t_divmod_2exp() requires 'mpz','int' arguments");
342            Py_DECREF((PyObject*)q);
343            Py_DECREF((PyObject*)r);
344            Py_DECREF(result);
345            return NULL;
346        }
347        mpz_tdiv_q_2exp(q->z, tempx->z, nbits);
348        mpz_tdiv_r_2exp(r->z, tempx->z, nbits);
349        Py_DECREF((PyObject*)tempx);
350    }
351    PyTuple_SET_ITEM(result, 0, (PyObject*)q);
352    PyTuple_SET_ITEM(result, 1, (PyObject*)r);
353    return result;
354}
355
356PyDoc_STRVAR(doc_gmpy_t_div_2exp,
357"t_div_2exp(x, n) -> quotient\n\n"
358"Return the quotient of x divided by 2**n. The quotient is rounded\n"
359"towards zero (truncation). n must be >0.");
360
361static PyObject *
362Pygmpy_t_div_2exp(PyObject *self, PyObject *args)
363{
364    mp_bitcnt_t nbits;
365    PyObject *x;
366    PympzObject *result, *tempx;
367
368    if (PyTuple_GET_SIZE(args) != 2) {
369        TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments");
370        return NULL;
371    }
372
373    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
374    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
375        return NULL;
376    }
377
378    x = PyTuple_GET_ITEM(args, 0);
379    if (!(result = (PympzObject*)Pympz_new()))
380        return NULL;
381    if (CHECK_MPZANY(x)) {
382        mpz_tdiv_q_2exp(result->z, Pympz_AS_MPZ(x), nbits);
383    }
384    else {
385        if (!(tempx = Pympz_From_Integer(x))) {
386            TYPE_ERROR("t_div_2exp() requires 'mpz','int' arguments");
387            Py_DECREF((PyObject*)result);
388            return NULL;
389        }
390        mpz_tdiv_q_2exp(result->z, tempx->z, nbits);
391        Py_DECREF((PyObject*)tempx);
392    }
393    return (PyObject*)result;
394}
395
396PyDoc_STRVAR(doc_gmpy_t_mod_2exp,
397"t_mod_2exp(x, n) -> remainder\n\n"
398"Return the remainder of x divided by 2**n. The remainder will have\n"
399"the same sign as x. x must be an integer. n must be >0.");
400
401static PyObject *
402Pygmpy_t_mod_2exp(PyObject *self, PyObject *args)
403{
404    mp_bitcnt_t nbits;
405    PyObject *x;
406    PympzObject *result, *tempx;
407
408    if (PyTuple_GET_SIZE(args) != 2) {
409        TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments");
410        return NULL;
411    }
412
413    nbits = MP_BITCNT_FROM_INTEGER(PyTuple_GET_ITEM(args, 1));
414    if (nbits == (mp_bitcnt_t)-1 && PyErr_Occurred()) {
415        return NULL;
416    }
417
418    x = PyTuple_GET_ITEM(args, 0);
419    if (!(result = (PympzObject*)Pympz_new()))
420        return NULL;
421
422    if (CHECK_MPZANY(x)) {
423        mpz_tdiv_r_2exp(result->z, Pympz_AS_MPZ(x), nbits);
424    }
425    else {
426        if (!(tempx = Pympz_From_Integer(x))) {
427            TYPE_ERROR("t_mod_2exp() requires 'mpz','int' arguments");
428            Py_DECREF((PyObject*)result);
429            return NULL;
430        }
431        mpz_tdiv_r_2exp(result->z, tempx->z, nbits);
432        Py_DECREF((PyObject*)tempx);
433    }
434    return (PyObject*)result;
435}
436
437/*
438 **************************************************************************
439 * pack and unpack methods
440 *
441 * Both pack and unpack use a devious trick when stuffing values into the
442 * internal structure of an mpz_t. By setting a bit beyond the range of
443 * interest, we are guaranteed that memory will remain available. When
444 * the bit is cleared, it also triggers normalization of the value by
445 * accounting for leading bits that are zero.
446 **************************************************************************
447 */
448
449PyDoc_STRVAR(doc_gmpy_pack,
450"pack(lst, n) -> mpz\n\n"
451"Pack a list of integers 'lst' into a single 'mpz' by concatenating\n"
452"each integer element of 'lst' after padding to length n bits. Raises\n"
453"an error if any integer is negative or greater than n bits in\n"
454"length.");
455
456static PyObject *
457Pygmpy_pack(PyObject *self, PyObject *args)
458{
459    Py_ssize_t nbits, total_bits, index, lst_count, i, temp_bits, limb_count, tempx_bits;
460    PyObject *lst;
461    mpz_t temp;
462    PympzObject *result, *tempx = 0;
463
464    if (PyTuple_GET_SIZE(args) != 2) {
465        TYPE_ERROR("pack() requires 'list','int' arguments");
466        return NULL;
467    }
468
469    nbits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1));
470    if (nbits == -1 && PyErr_Occurred()) {
471        TYPE_ERROR("pack() requires 'list','int' arguments");
472        return NULL;
473    }
474
475    if (nbits <= 0) {
476        VALUE_ERROR("pack() requires n > 0");
477        return NULL;
478    }
479
480    if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) {
481        TYPE_ERROR("pack() requires 'list','int' arguments");
482        return NULL;
483    }
484
485    if (!(result = (PympzObject*)Pympz_new()))
486        return NULL;
487
488    lst = PyTuple_GET_ITEM(args, 0);
489    lst_count = PyList_GET_SIZE(lst);
490    total_bits = nbits * lst_count;
491
492    mpz_set_ui(result->z, 0);
493    mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2));
494
495    mpz_inoc(temp);
496    mpz_set_ui(temp, 0);
497    limb_count = 0;
498    tempx_bits = 0;
499
500    for (index = 0; index < lst_count; index++) {
501        if (!(tempx = Pympz_From_Integer(PyList_GetItem(lst, index)))
502            || (mpz_sgn(tempx->z) < 0)
503            || (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) {
504            TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits");
505            mpz_cloc(temp);
506            Py_XDECREF((PyObject*)tempx);
507            Py_DECREF((PyObject*)result);
508            return NULL;
509        }
510        mpz_mul_2exp(tempx->z, tempx->z, tempx_bits);
511        mpz_add(temp, temp, tempx->z);
512        tempx_bits += nbits;
513        i = 0;
514        temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp);
515        while (tempx_bits >= mp_bits_per_limb) {
516            if (temp_bits > 0) {
517                result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i);
518            }
519            i += 1;
520            tempx_bits -= mp_bits_per_limb;
521            limb_count += 1;
522            temp_bits -= mp_bits_per_limb;
523        }
524        if (temp_bits > 0) {
525            mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * i);
526        }
527        else {
528            mpz_set_ui(temp, 0);
529        }
530        Py_DECREF((PyObject*)tempx);
531    }
532    result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0);
533    mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2));
534    mpz_cloc(temp);
535    return (PyObject*)result;
536}
537
538PyDoc_STRVAR(doc_gmpy_unpack,
539"unpack(x, n) -> list\n\n"
540"Unpack an integer 'x' into a list of n-bit values. Equivalent to\n"
541"repeated division by 2**n. Raises error if 'x' is negative.");
542
543static PyObject *
544Pygmpy_unpack(PyObject *self, PyObject *args)
545{
546    Py_ssize_t nbits, total_bits, index = 0, lst_count, i, temp_bits = 0, extra_bits = 0;
547    Py_ssize_t guard_bit, lst_ptr = 0;
548    PyObject *result;
549    mpz_t temp;
550    mp_limb_t extra = 0;
551    PympzObject *item, *tempx = 0;
552
553    if (PyTuple_GET_SIZE(args) != 2) {
554        TYPE_ERROR("unpack() requires 'int','int' arguments");
555        return NULL;
556    }
557
558    nbits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 1));
559    if (nbits == -1 && PyErr_Occurred()) {
560        TYPE_ERROR("unpack() requires 'int','int' arguments");
561        return NULL;
562    }
563
564    if (nbits <= 0) {
565        VALUE_ERROR("unpack() requires n > 0");
566        return NULL;
567    }
568
569    if (!(tempx = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)))) {
570        TYPE_ERROR("unpack() requires 'int','int' arguments");
571        return NULL;
572    }
573
574    if (mpz_sgn(tempx->z) < 0) {
575        VALUE_ERROR("unpack() requires x >= 0");
576        return NULL;
577    }
578
579    total_bits = mpz_sizeinbase(tempx->z, 2) * mpz_sgn(tempx->z);
580    lst_count = total_bits / nbits;
581    if ((total_bits % nbits) || !lst_count)
582        lst_count += 1;
583
584    if (!(result = PyList_New(lst_count))) {
585        Py_DECREF((PyObject*)tempx);
586        return NULL;
587    }
588
589    if (mpz_sgn(tempx->z) == 0) {
590        if (!(item = (PympzObject*)Pympz_new())) {
591            Py_DECREF((PyObject*)tempx);
592            Py_DECREF(result);
593            return NULL;
594        }
595        mpz_set_ui(item->z, 0);
596        PyList_SET_ITEM(result, 0, (PyObject*)item);
597        Py_DECREF((PyObject*)tempx);
598        return result;
599    }
600
601    mpz_inoc(temp);
602    guard_bit = nbits + (2 * mp_bits_per_limb);
603
604    while (lst_ptr < lst_count) {
605        i = 0;
606        temp_bits = 0;
607        mpz_set_ui(temp, 0);
608        mpz_setbit(temp, guard_bit);
609        while (temp_bits + extra_bits < nbits) {
610            temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++);
611            temp_bits += mp_bits_per_limb;
612        }
613        mpz_clrbit(temp, guard_bit);
614        mpz_mul_2exp(temp, temp, extra_bits);
615        if (mpz_sgn(temp) == 0 && extra != 0) {
616            mpz_set_ui(temp, 1);
617            temp->_mp_d[0] = extra;
618        }
619        else {
620           mpn_add_1(temp->_mp_d, temp->_mp_d, mpz_size(temp), extra);
621        }
622        temp_bits += extra_bits;
623
624        while ((lst_ptr < lst_count) && (temp_bits >= nbits)) {
625            if(!(item = (PympzObject*)Pympz_new())) {
626                mpz_cloc(temp);
627                Py_DECREF((PyObject*)tempx);
628                Py_DECREF(result);
629                return NULL;
630            }
631            mpz_tdiv_r_2exp(item->z, temp, nbits);
632            PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item);
633            mpz_tdiv_q_2exp(temp, temp, nbits);
634            temp_bits -= nbits;
635        }
636        extra = mpz_getlimbn(temp, 0);
637        extra_bits = temp_bits;
638    }
639    Py_DECREF((PyObject*)tempx);
640    mpz_cloc(temp);
641    return result;
642}
643
644