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