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