/ src / gmpy2_mpz_bitops.c
gmpy2_mpz_bitops.c
  1  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2   * gmpy2_mpz_bitops.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  PyDoc_STRVAR(doc_bit_length_method,
 28  "x.bit_length() -> int\n\n"
 29  "Return the number of significant bits in the radix-2\n"
 30  "representation of x. Note: mpz(0).bit_length() returns 0.");
 31  
 32  static PyObject *
 33  GMPy_MPZ_bit_length_method(PyObject *self, PyObject *other)
 34  {
 35      mp_bitcnt_t n = 0;
 36  
 37      if (mpz_size(MPZ(self)))
 38          n = mpz_sizeinbase(MPZ(self), 2);
 39  
 40      return PyIntOrLong_FromMpBitCnt(n);
 41  }
 42  
 43  PyDoc_STRVAR(doc_bit_length_function,
 44  "bit_length(x) -> int\n\n"
 45  "Return the number of significant bits in the radix-2\n"
 46  "representation of x. Note: bit_length(0) returns 0.");
 47  
 48  static PyObject *
 49  GMPy_MPZ_bit_length_function(PyObject *self, PyObject *other)
 50  {
 51      mp_bitcnt_t n = 0;
 52      MPZ_Object* tempx;
 53  
 54      if (!(tempx = GMPy_MPZ_From_Integer(other, NULL))) {
 55          TYPE_ERROR("bit_length() requires 'mpz' argument");
 56          return NULL;
 57      }
 58      if (mpz_size(MPZ(tempx)))
 59          n = mpz_sizeinbase(tempx->z, 2);
 60  
 61      Py_DECREF((PyObject*)tempx);
 62      return PyIntOrLong_FromMpBitCnt(n);
 63  }
 64  
 65  PyDoc_STRVAR(doc_bit_mask,
 66  "bit_mask(n) -> mpz\n\n"
 67  "Return an 'mpz' exactly n bits in length with all bits set.\n");
 68  
 69  static PyObject *
 70  GMPy_MPZ_bit_mask(PyObject *self, PyObject *other)
 71  {
 72      mp_bitcnt_t n = 0;
 73      MPZ_Object* result;
 74  
 75      n = mp_bitcnt_t_From_Integer(other);
 76      if (n == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
 77          return NULL;
 78      }
 79  
 80      if (!(result = GMPy_MPZ_New(NULL)))
 81          return NULL;
 82  
 83      mpz_set_ui(result->z, 1);
 84      mpz_mul_2exp(result->z, result->z, n);
 85      mpz_sub_ui(result->z, result->z, 1);
 86  
 87      return (PyObject*)result;
 88  }
 89  
 90  /* return scan0/scan1 for an mpz */
 91  PyDoc_STRVAR(doc_bit_scan0_method,
 92  "x.bit_scan0(n=0) -> int\n\n"
 93  "Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
 94  "If there are no more 0-bits in x at or above index n (which can\n"
 95  "only happen for x<0, assuming an infinitely long 2's complement\n"
 96  "format), then None is returned.");
 97  
 98  static PyObject *
 99  GMPy_MPZ_bit_scan0_method(PyObject *self, PyObject *args)
100  {
101      mp_bitcnt_t index, starting_bit = 0;
102  
103      if (PyTuple_GET_SIZE(args) == 1) {
104          starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 0));
105          if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
106              return NULL;
107          }
108      }
109  
110      index = mpz_scan0(MPZ(self), starting_bit);
111  
112      if (index == (mp_bitcnt_t)(-1)) {
113          Py_RETURN_NONE;
114      }
115      else {
116          return PyIntOrLong_FromMpBitCnt(index);
117      }
118  }
119  
120  PyDoc_STRVAR(doc_bit_scan0_function,
121  "bit_scan0(x, n=0) -> int\n\n"
122  "Return the index of the first 0-bit of x with index >= n. n >= 0.\n"
123  "If there are no more 0-bits in x at or above index n (which can\n"
124  "only happen for x<0, assuming an infinitely long 2's complement\n"
125  "format), then None is returned.");
126  
127  static PyObject *
128  GMPy_MPZ_bit_scan0_function(PyObject *self, PyObject *args)
129  {
130      mp_bitcnt_t index, starting_bit = 0;
131      MPZ_Object *tempx = NULL;
132  
133      if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_SIZE(args) > 2) {
134          goto err;
135      }
136  
137      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
138          goto err;
139      }
140  
141      if (PyTuple_GET_SIZE(args) == 2) {
142          starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
143          if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
144              goto err_index;
145          }
146      }
147  
148      index = mpz_scan0(tempx->z, starting_bit);
149  
150      Py_DECREF((PyObject*)tempx);
151      if (index == (mp_bitcnt_t)(-1)) {
152          Py_RETURN_NONE;
153      }
154      else {
155          return PyIntOrLong_FromMpBitCnt(index);
156      }
157  
158    err:
159      TYPE_ERROR("bit_scan0() requires 'mpz',['int'] arguments");
160    err_index:
161      Py_XDECREF((PyObject*)tempx);
162      return NULL;
163  }
164  
165  PyDoc_STRVAR(doc_bit_scan1_method,
166  "x.bit_scan1(n=0) -> int\n\n"
167  "Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
168  "If there are no more 1-bits in x at or above index n (which can\n"
169  "only happen for x>=0, assuming an infinitely long 2's complement\n"
170  "format), then None is returned.");
171  
172  static PyObject *
173  GMPy_MPZ_bit_scan1_method(PyObject *self, PyObject *args)
174  {
175      mp_bitcnt_t index, starting_bit = 0;
176  
177      if (PyTuple_GET_SIZE(args) == 1) {
178          starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 0));
179          if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
180              return NULL;
181          }
182      }
183  
184      index = mpz_scan1(MPZ(self), starting_bit);
185  
186      if (index == (mp_bitcnt_t)(-1)) {
187          Py_RETURN_NONE;
188      }
189      else {
190          return PyIntOrLong_FromMpBitCnt(index);
191      }
192  }
193  
194  PyDoc_STRVAR(doc_bit_scan1_function,
195  "bit_scan1(x, n=0) -> int\n\n"
196  "Return the index of the first 1-bit of x with index >= n. n >= 0.\n"
197  "If there are no more 1-bits in x at or above index n (which can\n"
198  "only happen for x>=0, assuming an infinitely long 2's complement\n"
199  "format), then None is returned.");
200  
201  static PyObject *
202  GMPy_MPZ_bit_scan1_function(PyObject *self, PyObject *args)
203  {
204      mp_bitcnt_t index, starting_bit = 0;
205      MPZ_Object *tempx = NULL;
206  
207      if (PyTuple_GET_SIZE(args) == 0 || PyTuple_GET_SIZE(args) > 2) {
208          goto err;
209      }
210  
211      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
212          goto err;
213      }
214  
215      if (PyTuple_GET_SIZE(args) == 2) {
216          starting_bit = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
217          if (starting_bit == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
218              goto err_index;
219          }
220      }
221  
222      index = mpz_scan1(tempx->z, starting_bit);
223  
224      Py_DECREF((PyObject*)tempx);
225      if (index == (mp_bitcnt_t)(-1)) {
226          Py_RETURN_NONE;
227      }
228      else {
229          return PyIntOrLong_FromMpBitCnt(index);
230      }
231  
232    err:
233      TYPE_ERROR("bit_scan1() requires 'mpz',['int'] arguments");
234    err_index:
235      Py_XDECREF((PyObject*)tempx);
236      return NULL;
237  }
238  
239  /* get & return one bit from an mpz */
240  PyDoc_STRVAR(doc_bit_test_function,
241  "bit_test(x, n) -> bool\n\n"
242  "Return the value of the n-th bit of x.");
243  
244  static PyObject *
245  GMPy_MPZ_bit_test_function(PyObject *self, PyObject *args)
246  {
247      mp_bitcnt_t bit_index;
248      int temp;
249      MPZ_Object *tempx = NULL;
250  
251      if (PyTuple_GET_SIZE(args) != 2) {
252          goto err;
253      }
254  
255      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL))) {
256          goto err;
257      }
258  
259      bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
260      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
261          goto err_index;
262      }
263  
264      temp = mpz_tstbit(tempx->z, bit_index);
265      Py_DECREF((PyObject*)tempx);
266  
267      if (temp)
268          Py_RETURN_TRUE;
269      else
270          Py_RETURN_FALSE;
271  
272    err:
273      TYPE_ERROR("bit_test() requires 'mpz','int' arguments");
274    err_index:
275      Py_XDECREF((PyObject*)tempx);
276      return NULL;
277  }
278  
279  PyDoc_STRVAR(doc_bit_test_method,
280  "x.bit_test(n) -> bool\n\n"
281  "Return the value of the n-th bit of x.");
282  
283  static PyObject *
284  GMPy_MPZ_bit_test_method(PyObject *self, PyObject *other)
285  {
286      mp_bitcnt_t bit_index;
287  
288      bit_index = mp_bitcnt_t_From_Integer(other);
289      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
290          return NULL;
291      }
292  
293      if (mpz_tstbit(MPZ(self), bit_index))
294          Py_RETURN_TRUE;
295      else
296          Py_RETURN_FALSE;
297  }
298  
299  PyDoc_STRVAR(doc_bit_clear_function,
300  "bit_clear(x, n) -> mpz\n\n"
301  "Return a copy of x with the n-th bit cleared.");
302  
303  static PyObject *
304  GMPy_MPZ_bit_clear_function(PyObject *self, PyObject *args)
305  {
306      mp_bitcnt_t bit_index;
307      MPZ_Object *result = NULL, *tempx = NULL;
308  
309      if (PyTuple_GET_SIZE(args) != 2)
310          goto err;
311  
312      if (!(result = GMPy_MPZ_New(NULL)))
313          return NULL;
314  
315      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
316          goto err;
317  
318      bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
319      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
320          goto err_index;
321  
322      mpz_set(result->z, tempx->z);
323      mpz_clrbit(result->z, bit_index);
324  
325      Py_DECREF((PyObject*)tempx);
326      return (PyObject*)result;
327  
328    err:
329      TYPE_ERROR("bit_clear() requires 'mpz','int' arguments");
330    err_index:
331      Py_XDECREF((PyObject*)result);
332      Py_XDECREF((PyObject*)tempx);
333      return NULL;
334  }
335  
336  PyDoc_STRVAR(doc_bit_clear_method,
337  "x.bit_clear(n) -> mpz\n\n"
338  "Return a copy of x with the n-th bit cleared.");
339  
340  static PyObject *
341  GMPy_MPZ_bit_clear_method(PyObject *self, PyObject *other)
342  {
343      mp_bitcnt_t bit_index;
344      MPZ_Object *result = NULL;
345  
346      if (!(result = GMPy_MPZ_New(NULL)))
347          return NULL;
348  
349      bit_index = mp_bitcnt_t_From_Integer(other);
350      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
351          Py_DECREF(result);
352          return NULL;
353      }
354  
355      mpz_set(result->z, MPZ(self));
356      mpz_clrbit(result->z, bit_index);
357      return (PyObject*)result;
358  }
359  
360  PyDoc_STRVAR(doc_bit_set_function,
361  "bit_set(x, n) -> mpz\n\n"
362  "Return a copy of x with the n-th bit set.");
363  
364  static PyObject *
365  GMPy_MPZ_bit_set_function(PyObject *self, PyObject *args)
366  {
367      mp_bitcnt_t bit_index;
368      MPZ_Object *result = NULL, *tempx = NULL;
369  
370      if (PyTuple_GET_SIZE(args) != 2)
371          goto err;
372  
373      if (!(result = GMPy_MPZ_New(NULL)))
374          return NULL;
375  
376      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
377          goto err;
378  
379      bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
380      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
381          goto err_index;
382  
383      mpz_set(result->z, tempx->z);
384      mpz_setbit(result->z, bit_index);
385  
386      Py_DECREF((PyObject*)tempx);
387      return (PyObject*)result;
388  
389    err:
390      TYPE_ERROR("bit_set() requires 'mpz','int' arguments");
391    err_index:
392      Py_XDECREF((PyObject*)result);
393      Py_XDECREF((PyObject*)tempx);
394      return NULL;
395  }
396  
397  PyDoc_STRVAR(doc_bit_set_method,
398  "x.bit_set(n) -> mpz\n\n"
399  "Return a copy of x with the n-th bit set.");
400  
401  static PyObject *
402  GMPy_MPZ_bit_set_method(PyObject *self, PyObject *other)
403  {
404      mp_bitcnt_t bit_index;
405      MPZ_Object *result = NULL;
406  
407      if (!(result = GMPy_MPZ_New(NULL)))
408          return NULL;
409  
410      bit_index = mp_bitcnt_t_From_Integer(other);
411      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
412          Py_DECREF(result);
413          return NULL;
414      }
415  
416      mpz_set(result->z, MPZ(self));
417      mpz_setbit(result->z, bit_index);
418      return (PyObject*)result;
419  }
420  
421  PyDoc_STRVAR(doc_bit_flip_function,
422  "bit_flip(x, n) -> mpz\n\n"
423  "Return a copy of x with the n-th bit inverted.");
424  
425  static PyObject *
426  GMPy_MPZ_bit_flip_function(PyObject *self, PyObject *args)
427  {
428      mp_bitcnt_t bit_index;
429      MPZ_Object *result = NULL, *tempx = NULL;
430  
431      if (PyTuple_GET_SIZE(args) != 2)
432          goto err;
433  
434      if (!(result = GMPy_MPZ_New(NULL)))
435          return NULL;
436  
437      if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)))
438          goto err;
439  
440      bit_index = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1));
441      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred())
442          goto err_index;
443  
444      mpz_set(result->z, tempx->z);
445      mpz_combit(result->z, bit_index);
446  
447      Py_DECREF((PyObject*)tempx);
448      return (PyObject*)result;
449  
450    err:
451      TYPE_ERROR("bit_flip() requires 'mpz','int' arguments");
452    err_index:
453      Py_XDECREF((PyObject*)result);
454      Py_XDECREF((PyObject*)tempx);
455      return NULL;
456  }
457  
458  PyDoc_STRVAR(doc_bit_flip_method,
459  "x.bit_flip(n) -> mpz\n\n"
460  "Return a copy of x with the n-th bit inverted.");
461  
462  static PyObject *
463  GMPy_MPZ_bit_flip_method(PyObject *self, PyObject *other)
464  {
465      mp_bitcnt_t bit_index;
466      MPZ_Object *result = NULL;
467  
468      if (!(result = GMPy_MPZ_New(NULL)))
469          return NULL;
470  
471      bit_index = mp_bitcnt_t_From_Integer(other);
472      if (bit_index == (mp_bitcnt_t)(-1) && PyErr_Occurred()) {
473          Py_DECREF(result);
474          return NULL;
475      }
476  
477      mpz_set(result->z, MPZ(self));
478      mpz_combit(result->z, bit_index);
479      return (PyObject*)result;
480  }
481  
482  static PyObject *
483  GMPy_MPZ_Invert_Slot(MPZ_Object *self)
484  {
485      MPZ_Object *result;
486  
487      if ((result = GMPy_MPZ_New(NULL)))
488          mpz_com(result->z, MPZ(self));
489  
490      return (PyObject*)result;
491  }
492  
493  static PyObject *
494  GMPy_MPZ_And_Slot(PyObject *self, PyObject *other)
495  {
496      MPZ_Object *result;
497  
498      if (CHECK_MPZANY(self)) {
499          if (CHECK_MPZANY(other)) {
500              if (!(result = GMPy_MPZ_New(NULL)))
501                  return NULL;
502              mpz_and(result->z, MPZ(self), MPZ(other));
503          }
504          else {
505              if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
506                  return NULL;
507              mpz_and(result->z, MPZ(self), result->z);
508          }
509      }
510      else if (CHECK_MPZANY(other)) {
511          if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
512              return NULL;
513          mpz_and(result->z, result->z, MPZ(other));
514      }
515      else {
516          Py_RETURN_NOTIMPLEMENTED;
517      }
518      return (PyObject*)result;
519  }
520  
521  static PyObject *
522  GMPy_MPZ_Ior_Slot(PyObject *self, PyObject *other)
523  {
524      MPZ_Object *result;
525  
526      if (CHECK_MPZANY(self)) {
527          if (CHECK_MPZANY(other)) {
528              if (!(result = GMPy_MPZ_New(NULL)))
529                  return NULL;
530              mpz_ior(result->z, MPZ(self), MPZ(other));
531          }
532          else {
533              if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
534                  return NULL;
535              mpz_ior(result->z, MPZ(self), result->z);
536          }
537      }
538      else if (CHECK_MPZANY(other)) {
539          if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
540              return NULL;
541          mpz_ior(result->z, result->z, MPZ(other));
542      }
543      else {
544          Py_RETURN_NOTIMPLEMENTED;
545      }
546      return (PyObject*)result;
547  }
548  
549  static PyObject *
550  GMPy_MPZ_Xor_Slot(PyObject *self, PyObject *other)
551  {
552      MPZ_Object *result;
553  
554      if (CHECK_MPZANY(self)) {
555          if (CHECK_MPZANY(other)) {
556              if (!(result = GMPy_MPZ_New(NULL)))
557                  return NULL;
558              mpz_xor(result->z, MPZ(self), MPZ(other));
559          }
560          else {
561              if (!(result = GMPy_MPZ_From_Integer(other, NULL)))
562                  return NULL;
563              mpz_xor(result->z, MPZ(self), result->z);
564          }
565      }
566      else if (CHECK_MPZANY(other)) {
567          if (!(result = GMPy_MPZ_From_Integer(self, NULL)))
568              return NULL;
569          mpz_xor(result->z, result->z, MPZ(other));
570      }
571      else {
572          Py_RETURN_NOTIMPLEMENTED;
573      }
574      return (PyObject*)result;
575  }
576  
577  static PyObject *
578  GMPy_MPZ_Rshift_Slot(PyObject *self, PyObject *other)
579  {
580      mp_bitcnt_t count;
581      MPZ_Object *result, *tempx;
582  
583      count = mp_bitcnt_t_From_Integer(other);
584      if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
585          return NULL;
586  
587      if (!(result = GMPy_MPZ_New(NULL)))
588          return NULL;
589  
590      if (CHECK_MPZANY(self)) {
591          mpz_fdiv_q_2exp(result->z, MPZ(self), count);
592          return (PyObject*)result;
593      }
594      else {
595          if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
596              Py_XDECREF((PyObject*)result);
597              Py_XDECREF((PyObject*)tempx);
598              return NULL;
599          }
600  
601          mpz_fdiv_q_2exp(result->z, tempx->z, count);
602          Py_DECREF((PyObject*)tempx);
603          return (PyObject*)result;
604      }
605  }
606  
607  static PyObject *
608  GMPy_MPZ_Lshift_Slot(PyObject *self, PyObject *other)
609  {
610      mp_bitcnt_t count;
611      MPZ_Object *result, *tempx;
612  
613      count = mp_bitcnt_t_From_Integer(other);
614      if ((count == (mp_bitcnt_t)(-1)) && PyErr_Occurred())
615          return NULL;
616  
617      if (!(result = GMPy_MPZ_New(NULL)))
618          return NULL;
619  
620      if (CHECK_MPZANY(self)) {
621          mpz_mul_2exp(result->z, MPZ(self), count);
622          return (PyObject*)result;
623      }
624      else {
625          if (!(tempx = GMPy_MPZ_From_Integer(self, NULL))) {
626              Py_XDECREF((PyObject*)result);
627              Py_XDECREF((PyObject*)tempx);
628              return NULL;
629          }
630  
631          mpz_mul_2exp(result->z, tempx->z, count);
632          Py_DECREF((PyObject*)tempx);
633          return (PyObject*)result;
634      }
635  }
636  
637  PyDoc_STRVAR(doc_popcount,
638  "popcount(x) -> int\n\n"
639  "Return the number of 1-bits set in x. If x<0, the number of\n"
640  "1-bits is infinite so -1 is returned in that case.");
641  
642  static PyObject *
643  GMPy_MPZ_popcount(PyObject *self, PyObject *other)
644  {
645      mp_bitcnt_t n;
646      MPZ_Object *tempx;
647  
648      if ((tempx = GMPy_MPZ_From_Integer(other, NULL))) {
649          n = mpz_popcount(tempx->z);
650          Py_DECREF((PyObject*)tempx);
651          if (n == (mp_bitcnt_t)(-1))
652              return PyLong_FromLong(-1);
653          else
654              return PyIntOrLong_FromMpBitCnt(n);
655      }
656      else {
657          TYPE_ERROR("popcount() requires 'mpz' argument");
658          return NULL;
659      }
660  }
661  
662  PyDoc_STRVAR(doc_hamdist,
663  "hamdist(x, y) -> int\n\n"
664  "Return the Hamming distance (number of bit-positions where the\n"
665  "bits differ) between integers x and y.");
666  
667  static PyObject *
668  GMPy_MPZ_hamdist(PyObject *self, PyObject *args)
669  {
670      PyObject *result = NULL;
671      MPZ_Object *tempx = NULL, *tempy = NULL;
672  
673      if (PyTuple_GET_SIZE(args) != 2)
674          goto err;
675  
676      tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL);
677      tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL);
678      if (!tempx || !tempy)
679          goto err;
680  
681      result = PyIntOrLong_FromMpBitCnt(mpz_hamdist(tempx->z, tempy->z));
682      Py_DECREF((PyObject*)tempx);
683      Py_DECREF((PyObject*)tempy);
684      return result;
685  
686    err:
687      TYPE_ERROR("hamdist() requires 'mpz','mpz' arguments");
688      Py_XDECREF((PyObject*)tempx);
689      Py_XDECREF((PyObject*)tempy);
690      return NULL;
691  }
692