1*f14fb602SLionel Sambuc /* $NetBSD: popcount32.c,v 1.4 2011/08/21 21:25:04 dholland Exp $ */ 2b6cbf720SGianluca Guida /*- 3b6cbf720SGianluca Guida * Copyright (c) 2009 The NetBSD Foundation, Inc. 4b6cbf720SGianluca Guida * All rights reserved. 5b6cbf720SGianluca Guida * 6b6cbf720SGianluca Guida * This code is derived from software contributed to The NetBSD Foundation 7b6cbf720SGianluca Guida * by Joerg Sonnenberger. 8b6cbf720SGianluca Guida * 9b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without 10b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions 11b6cbf720SGianluca Guida * are met: 12b6cbf720SGianluca Guida * 13b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright 14b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer. 15b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright 16b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer in 17b6cbf720SGianluca Guida * the documentation and/or other materials provided with the 18b6cbf720SGianluca Guida * distribution. 19b6cbf720SGianluca Guida * 20b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21b6cbf720SGianluca Guida * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22b6cbf720SGianluca Guida * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23b6cbf720SGianluca Guida * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24b6cbf720SGianluca Guida * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25b6cbf720SGianluca Guida * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26b6cbf720SGianluca Guida * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27b6cbf720SGianluca Guida * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28b6cbf720SGianluca Guida * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29b6cbf720SGianluca Guida * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30b6cbf720SGianluca Guida * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b6cbf720SGianluca Guida * SUCH DAMAGE. 32b6cbf720SGianluca Guida */ 33b6cbf720SGianluca Guida 34b6cbf720SGianluca Guida #include <sys/cdefs.h> 35*f14fb602SLionel Sambuc __RCSID("$NetBSD: popcount32.c,v 1.4 2011/08/21 21:25:04 dholland Exp $"); 36b6cbf720SGianluca Guida 37b6cbf720SGianluca Guida #if !defined(_KERNEL) && !defined(_STANDALONE) 38b6cbf720SGianluca Guida #include <limits.h> 39*f14fb602SLionel Sambuc #include <stdint.h> 40b6cbf720SGianluca Guida #include <strings.h> 41b6cbf720SGianluca Guida #else 42b6cbf720SGianluca Guida #include <lib/libkern/libkern.h> 43b6cbf720SGianluca Guida #include <machine/limits.h> 44b6cbf720SGianluca Guida #endif 45b6cbf720SGianluca Guida 46b6cbf720SGianluca Guida /* 47b6cbf720SGianluca Guida * This a hybrid algorithm for bit counting between parallel counting and 48b6cbf720SGianluca Guida * using multiplication. The idea is to sum up the bits in each Byte, so 49b6cbf720SGianluca Guida * that the final accumulation can be done with a single multiplication. 50b6cbf720SGianluca Guida * If the platform has a slow multiplication instruction, it can be replaced 51b6cbf720SGianluca Guida * by the commented out version below. 52b6cbf720SGianluca Guida */ 53b6cbf720SGianluca Guida 54b6cbf720SGianluca Guida unsigned int 55b6cbf720SGianluca Guida popcount32(uint32_t v) 56b6cbf720SGianluca Guida { 57b6cbf720SGianluca Guida unsigned int c; 58b6cbf720SGianluca Guida 59b6cbf720SGianluca Guida v = v - ((v >> 1) & 0x55555555U); 60b6cbf720SGianluca Guida v = (v & 0x33333333U) + ((v >> 2) & 0x33333333U); 61b6cbf720SGianluca Guida v = (v + (v >> 4)) & 0x0f0f0f0fU; 62b6cbf720SGianluca Guida c = (v * 0x01010101U) >> 24; 63b6cbf720SGianluca Guida /* 64b6cbf720SGianluca Guida * v = (v >> 16) + v; 65b6cbf720SGianluca Guida * v = (v >> 8) + v; 66b6cbf720SGianluca Guida * c = v & 255; 67b6cbf720SGianluca Guida */ 68b6cbf720SGianluca Guida 69b6cbf720SGianluca Guida return c; 70b6cbf720SGianluca Guida } 71b6cbf720SGianluca Guida 72b6cbf720SGianluca Guida #if UINT_MAX == 0xffffffffU 73b6cbf720SGianluca Guida __strong_alias(popcount, popcount32) 74b6cbf720SGianluca Guida #endif 75b6cbf720SGianluca Guida 76b6cbf720SGianluca Guida #if ULONG_MAX == 0xffffffffU 77b6cbf720SGianluca Guida __strong_alias(popcountl, popcount32) 78b6cbf720SGianluca Guida #endif 79