xref: /netbsd-src/common/lib/libc/string/popcount32.c (revision 6ac68d00a5f3b4681ac3595dabcea47163b478d6)
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