1*6ac68d00Smatt /* $NetBSD: popcount32.c,v 1.5 2015/05/29 19:39:41 matt Exp $ */
20578c2adSjoerg /*-
30578c2adSjoerg * Copyright (c) 2009 The NetBSD Foundation, Inc.
40578c2adSjoerg * All rights reserved.
50578c2adSjoerg *
60578c2adSjoerg * This code is derived from software contributed to The NetBSD Foundation
70578c2adSjoerg * by Joerg Sonnenberger.
80578c2adSjoerg *
90578c2adSjoerg * Redistribution and use in source and binary forms, with or without
100578c2adSjoerg * modification, are permitted provided that the following conditions
110578c2adSjoerg * are met:
120578c2adSjoerg *
130578c2adSjoerg * 1. Redistributions of source code must retain the above copyright
140578c2adSjoerg * notice, this list of conditions and the following disclaimer.
150578c2adSjoerg * 2. Redistributions in binary form must reproduce the above copyright
160578c2adSjoerg * notice, this list of conditions and the following disclaimer in
170578c2adSjoerg * the documentation and/or other materials provided with the
180578c2adSjoerg * distribution.
190578c2adSjoerg *
200578c2adSjoerg * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
210578c2adSjoerg * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
220578c2adSjoerg * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
230578c2adSjoerg * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
240578c2adSjoerg * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
250578c2adSjoerg * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
260578c2adSjoerg * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
270578c2adSjoerg * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
280578c2adSjoerg * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
290578c2adSjoerg * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
300578c2adSjoerg * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
310578c2adSjoerg * SUCH DAMAGE.
320578c2adSjoerg */
330578c2adSjoerg
340578c2adSjoerg #include <sys/cdefs.h>
35*6ac68d00Smatt __RCSID("$NetBSD: popcount32.c,v 1.5 2015/05/29 19:39:41 matt Exp $");
360578c2adSjoerg
370578c2adSjoerg #if !defined(_KERNEL) && !defined(_STANDALONE)
3811e383c9Sjoerg #include <limits.h>
390a54ac30Sdholland #include <stdint.h>
400578c2adSjoerg #include <strings.h>
410578c2adSjoerg #else
420578c2adSjoerg #include <lib/libkern/libkern.h>
4311e383c9Sjoerg #include <machine/limits.h>
440578c2adSjoerg #endif
450578c2adSjoerg
46*6ac68d00Smatt #ifndef popcount32 // might be a builtin
47*6ac68d00Smatt
480578c2adSjoerg /*
490578c2adSjoerg * This a hybrid algorithm for bit counting between parallel counting and
500578c2adSjoerg * using multiplication. The idea is to sum up the bits in each Byte, so
510578c2adSjoerg * that the final accumulation can be done with a single multiplication.
520578c2adSjoerg * If the platform has a slow multiplication instruction, it can be replaced
530578c2adSjoerg * by the commented out version below.
540578c2adSjoerg */
550578c2adSjoerg
560578c2adSjoerg unsigned int
popcount32(uint32_t v)570578c2adSjoerg popcount32(uint32_t v)
580578c2adSjoerg {
590578c2adSjoerg unsigned int c;
600578c2adSjoerg
610578c2adSjoerg v = v - ((v >> 1) & 0x55555555U);
620578c2adSjoerg v = (v & 0x33333333U) + ((v >> 2) & 0x33333333U);
630578c2adSjoerg v = (v + (v >> 4)) & 0x0f0f0f0fU;
640578c2adSjoerg c = (v * 0x01010101U) >> 24;
650578c2adSjoerg /*
660578c2adSjoerg * v = (v >> 16) + v;
670578c2adSjoerg * v = (v >> 8) + v;
680578c2adSjoerg * c = v & 255;
690578c2adSjoerg */
700578c2adSjoerg
710578c2adSjoerg return c;
720578c2adSjoerg }
730578c2adSjoerg
7411e383c9Sjoerg #if UINT_MAX == 0xffffffffU
758e73e87cSdrochner __strong_alias(popcount, popcount32)
760578c2adSjoerg #endif
770578c2adSjoerg
780578c2adSjoerg #if ULONG_MAX == 0xffffffffU
798e73e87cSdrochner __strong_alias(popcountl, popcount32)
800578c2adSjoerg #endif
81*6ac68d00Smatt
82*6ac68d00Smatt #endif /* !popcount32 */
83