Home | History | Annotate | Line # | Download | only in generic
      1      1.1  mrg /* mpn_popcount, mpn_hamdist -- mpn bit population count/hamming distance.
      2      1.1  mrg 
      3  1.1.1.3  mrg Copyright 1994, 1996, 2000-2002, 2005, 2011, 2012 Free Software Foundation,
      4  1.1.1.3  mrg Inc.
      5      1.1  mrg 
      6      1.1  mrg This file is part of the GNU MP Library.
      7      1.1  mrg 
      8      1.1  mrg The GNU MP Library is free software; you can redistribute it and/or modify
      9  1.1.1.3  mrg it under the terms of either:
     10  1.1.1.3  mrg 
     11  1.1.1.3  mrg   * the GNU Lesser General Public License as published by the Free
     12  1.1.1.3  mrg     Software Foundation; either version 3 of the License, or (at your
     13  1.1.1.3  mrg     option) any later version.
     14  1.1.1.3  mrg 
     15  1.1.1.3  mrg or
     16  1.1.1.3  mrg 
     17  1.1.1.3  mrg   * the GNU General Public License as published by the Free Software
     18  1.1.1.3  mrg     Foundation; either version 2 of the License, or (at your option) any
     19  1.1.1.3  mrg     later version.
     20  1.1.1.3  mrg 
     21  1.1.1.3  mrg or both in parallel, as here.
     22      1.1  mrg 
     23      1.1  mrg The GNU MP Library is distributed in the hope that it will be useful, but
     24      1.1  mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     25  1.1.1.3  mrg or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     26  1.1.1.3  mrg for more details.
     27      1.1  mrg 
     28  1.1.1.3  mrg You should have received copies of the GNU General Public License and the
     29  1.1.1.3  mrg GNU Lesser General Public License along with the GNU MP Library.  If not,
     30  1.1.1.3  mrg see https://www.gnu.org/licenses/.  */
     31      1.1  mrg 
     32      1.1  mrg #include "gmp-impl.h"
     33      1.1  mrg 
     34      1.1  mrg #if OPERATION_popcount
     35      1.1  mrg #define FNAME mpn_popcount
     36      1.1  mrg #define POPHAM(u,v) u
     37      1.1  mrg #endif
     38      1.1  mrg 
     39      1.1  mrg #if OPERATION_hamdist
     40      1.1  mrg #define FNAME mpn_hamdist
     41      1.1  mrg #define POPHAM(u,v) u ^ v
     42      1.1  mrg #endif
     43      1.1  mrg 
     44      1.1  mrg mp_bitcnt_t
     45      1.1  mrg FNAME (mp_srcptr up,
     46      1.1  mrg #if OPERATION_hamdist
     47      1.1  mrg        mp_srcptr vp,
     48      1.1  mrg #endif
     49  1.1.1.2  mrg        mp_size_t n) __GMP_NOTHROW
     50      1.1  mrg {
     51      1.1  mrg   mp_bitcnt_t result = 0;
     52      1.1  mrg   mp_limb_t p0, p1, p2, p3, x, p01, p23;
     53      1.1  mrg   mp_size_t i;
     54      1.1  mrg 
     55      1.1  mrg   ASSERT (n >= 1);		/* Actually, this code handles any n, but some
     56      1.1  mrg 				   assembly implementations do not.  */
     57      1.1  mrg 
     58      1.1  mrg   for (i = n >> 2; i != 0; i--)
     59      1.1  mrg     {
     60      1.1  mrg       p0 = POPHAM (up[0], vp[0]);
     61      1.1  mrg       p0 -= (p0 >> 1) & MP_LIMB_T_MAX/3;				/* 2 0-2 */
     62      1.1  mrg       p0 = ((p0 >> 2) & MP_LIMB_T_MAX/5) + (p0 & MP_LIMB_T_MAX/5);	/* 4 0-4 */
     63      1.1  mrg 
     64      1.1  mrg       p1 = POPHAM (up[1], vp[1]);
     65      1.1  mrg       p1 -= (p1 >> 1) & MP_LIMB_T_MAX/3;				/* 2 0-2 */
     66      1.1  mrg       p1 = ((p1 >> 2) & MP_LIMB_T_MAX/5) + (p1 & MP_LIMB_T_MAX/5);	/* 4 0-4 */
     67      1.1  mrg 
     68      1.1  mrg       p01 = p0 + p1;							/* 8 0-8 */
     69      1.1  mrg       p01 = ((p01 >> 4) & MP_LIMB_T_MAX/17) + (p01 & MP_LIMB_T_MAX/17);	/* 8 0-16 */
     70      1.1  mrg 
     71      1.1  mrg       p2 = POPHAM (up[2], vp[2]);
     72      1.1  mrg       p2 -= (p2 >> 1) & MP_LIMB_T_MAX/3;				/* 2 0-2 */
     73      1.1  mrg       p2 = ((p2 >> 2) & MP_LIMB_T_MAX/5) + (p2 & MP_LIMB_T_MAX/5);	/* 4 0-4 */
     74      1.1  mrg 
     75      1.1  mrg       p3 = POPHAM (up[3], vp[3]);
     76      1.1  mrg       p3 -= (p3 >> 1) & MP_LIMB_T_MAX/3;				/* 2 0-2 */
     77      1.1  mrg       p3 = ((p3 >> 2) & MP_LIMB_T_MAX/5) + (p3 & MP_LIMB_T_MAX/5);	/* 4 0-4 */
     78      1.1  mrg 
     79      1.1  mrg       p23 = p2 + p3;							/* 8 0-8 */
     80      1.1  mrg       p23 = ((p23 >> 4) & MP_LIMB_T_MAX/17) + (p23 & MP_LIMB_T_MAX/17);	/* 8 0-16 */
     81      1.1  mrg 
     82      1.1  mrg       x = p01 + p23;							/* 8 0-32 */
     83      1.1  mrg       x = (x >> 8) + x;							/* 8 0-64 */
     84      1.1  mrg       x = (x >> 16) + x;						/* 8 0-128 */
     85      1.1  mrg #if GMP_LIMB_BITS > 32
     86      1.1  mrg       x = ((x >> 32) & 0xff) + (x & 0xff);				/* 8 0-256 */
     87      1.1  mrg       result += x;
     88      1.1  mrg #else
     89      1.1  mrg       result += x & 0xff;
     90      1.1  mrg #endif
     91      1.1  mrg       up += 4;
     92      1.1  mrg #if OPERATION_hamdist
     93      1.1  mrg       vp += 4;
     94      1.1  mrg #endif
     95      1.1  mrg     }
     96      1.1  mrg 
     97      1.1  mrg   n &= 3;
     98      1.1  mrg   if (n != 0)
     99      1.1  mrg     {
    100      1.1  mrg       x = 0;
    101      1.1  mrg       do
    102      1.1  mrg 	{
    103      1.1  mrg 	  p0 = POPHAM (up[0], vp[0]);
    104      1.1  mrg 	  p0 -= (p0 >> 1) & MP_LIMB_T_MAX/3;				/* 2 0-2 */
    105      1.1  mrg 	  p0 = ((p0 >> 2) & MP_LIMB_T_MAX/5) + (p0 & MP_LIMB_T_MAX/5);	/* 4 0-4 */
    106      1.1  mrg 	  p0 = ((p0 >> 4) + p0) & MP_LIMB_T_MAX/17;			/* 8 0-8 */
    107      1.1  mrg 
    108      1.1  mrg 	  x += p0;
    109      1.1  mrg 	  up += 1;
    110      1.1  mrg #if OPERATION_hamdist
    111      1.1  mrg 	  vp += 1;
    112      1.1  mrg #endif
    113      1.1  mrg 	}
    114      1.1  mrg       while (--n);
    115      1.1  mrg 
    116      1.1  mrg       x = (x >> 8) + x;
    117      1.1  mrg       x = (x >> 16) + x;
    118      1.1  mrg #if GMP_LIMB_BITS > 32
    119      1.1  mrg       x = (x >> 32) + x;
    120      1.1  mrg #endif
    121      1.1  mrg       result += x & 0xff;
    122      1.1  mrg     }
    123      1.1  mrg 
    124      1.1  mrg   return result;
    125      1.1  mrg }
    126