Hamming weight
The Hamming weight of a string is the number of symbols that are different from the zero-symbol of the alphabet used. It is thus equivalent to the Hamming distance from the all-zero string of the same length. For the most typical case, a given set of bits, this is the number of bits set to 1, or the digit sum of the binary representation of a given number and the ℓ₁ norm of a bit vector. In this binary case, it is also called the population count, popcount, sideways sum, or bit summation.
| String | Hamming weight |
| 1110'1 | 4 |
| 11101'000 | 4 |
| 00000000 | 0 |
| 6780'12340567' | 10 |
History and usage
The Hamming weight is named after the American mathematician Richard Hamming, although he did not originate the notion. The Hamming weight of binary numbers was already used in 1899 by James W. L. Glaisher to give a formula for the number of odd binomial coefficients in a single row of Pascal's triangle. Irving S. Reed introduced a concept, equivalent to Hamming weight in the binary case, in 1954.Hamming weight is used in several disciplines including information theory, coding theory, and cryptography. Examples of applications of the Hamming weight include:
- In modular exponentiation by squaring, the number of modular multiplications required for an exponent e is log2 e + weight. This is the reason that the public key value e used in RSA is typically chosen to be a number of low Hamming weight.
- The Hamming weight determines path lengths between nodes in Chord distributed hash tables.
- IrisCode lookups in biometric databases are typically implemented by calculating the Hamming distance to each stored record.
- In computer chess programs using a bitboard representation, the Hamming weight of a bitboard gives the number of pieces of a given type remaining in the game, or the number of squares of the board controlled by one player's pieces, and is therefore an important contributing term to the value of a position.
- Hamming weight can be used to efficiently compute find first set using the identity ffs = pop. This is useful on platforms such as SPARC that have hardware Hamming weight instructions but no hardware find first set instruction.
- The Hamming weight operation can be interpreted as a conversion from the unary numeral system to binary numbers.
Efficient implementation
The population count of a bitstring is often needed in cryptography and other applications. The Hamming distance of two words A and B can be calculated as the Hamming weight of A xor B.The problem of how to implement it efficiently has been widely studied. A single operation for the calculation, or parallel operations on bit vectors are available on some processors. For processors lacking those features, the best solutions known are based on adding counts in a tree pattern. For example, to count the number of 1 bits in the 16-bit binary number a = 0110 1100 1011 1010, these operations can be done:
Here, the operations are as in C programming language, so means to shift X right by Y bits, X & Y means the bitwise AND of X and Y, and + is ordinary addition. The best algorithms known for this problem are based on the concept illustrated above and are given here:
//types and constants used in the functions below
//uint64_t is an unsigned 64-bit integer variable type
const uint64_t m1 = 0x5555555555555555; //binary: 0101...
const uint64_t m2 = 0x3333333333333333; //binary: 00110011..
const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; //binary: 4 zeros, 4 ones...
const uint64_t m8 = 0x00ff00ff00ff00ff; //binary: 8 zeros, 8 ones...
const uint64_t m16 = 0x0000ffff0000ffff; //binary: 16 zeros, 16 ones...
const uint64_t m32 = 0x00000000ffffffff; //binary: 32 zeros, 32 ones
const uint64_t h01 = 0x0101010101010101; //the sum of 256 to the power of 0,1,2,3...
//This is a naive implementation, shown for comparison,
//and to help in understanding the better functions.
//This algorithm uses 24 arithmetic operations.
int popcount64a
//This uses fewer arithmetic operations than any other known
//implementation on machines with slow multiplication.
//This algorithm uses 17 arithmetic operations.
int popcount64b
//This uses fewer arithmetic operations than any other known
//implementation on machines with fast multiplication.
//This algorithm uses 12 arithmetic operations, one of which is a multiply.
int popcount64c
The above implementations have the best worst-case behavior of any known algorithm. However, when a value is expected to have few nonzero bits, it may instead be more efficient to use algorithms that count these bits one at a time. As Wegner described in 1960, the bitwise AND of x with x − 1 differs from x only in zeroing out the least significant nonzero bit: subtracting 1 changes the rightmost string of 0s to 1s, and changes the rightmost 1 to a 0. If x originally had n bits that were 1, then after only n iterations of this operation, x will be reduced to zero. The following implementation is based on this principle.
//This is better when most bits in x are 0
//This algorithm works the same for all data sizes.
//This algorithm uses 3 arithmetic operations and 1 comparison/branch per "1" bit in x.
int popcount64d
Of interest here is the close relationship between Popcount, FFS and CLZ.
If greater memory usage is allowed, we can calculate the Hamming weight faster than the above methods. With unlimited memory, we could simply create a large lookup table of the Hamming weight of every 64 bit integer. If we can store a lookup table of the hamming function of every 16 bit integer, we can do the following to compute the Hamming weight of every 32 bit integer.
static uint8_t wordbits = ;
//This algorithm uses 3 arithmetic operations and 2 memory reads.
int popcount32e
//Optionally, the wordbits table could be filled using this function
int popcount32e_init
A recursive algorithm is given in Donovan & Kernighan
/* The weight of i can differ from the weight of i / 2
only in the least significant bit of i */
int popcount32e_init
Muła et al. have shown that a vectorized version of popcount64b can run faster than dedicated instructions.
The Harley–Seal algorithm is one of the fastest that also only needs integer operations.
Minimum weight
In error-correcting coding, the minimum Hamming weight, commonly referred to as the minimum weight wmin of a code is the weight of the lowest-weight non-zero code word. The weight w of a code word is the number of 1s in the word. For example, the word 11001010 has a weight of 4.In a linear block code the minimum weight is also the minimum Hamming distance and defines the error correction capability of the code. If wmin = n, then dmin = n and the code will correct up to dmin/2 errors.
Language support
Some C compilers provide intrinsic functions that provide bit counting facilities. For example, GCC includes a builtin function__builtin_popcount that will use a processor instruction if available or an efficient library implementation otherwise. LLVM-GCC has included this function since version 1.5 in June 2005.In the C++ Standard Library, the bit-array data structure
bitset has a count method that counts the number of bits that are set. In C++20, a new header was added, containing functions std::popcount and std::has_single_bit, taking arguments of unsigned integer types.In Java, the growable bit-array data structure has a method that counts the number of bits that are set. In addition, there are and functions to count bits in primitive 32-bit and 64-bit integers, respectively. Also, the arbitrary-precision integer class also has a method that counts bits.
In Python, the
int type has a bit_count method to count the number of bits set. This functionality was introduced in Python 3.10, released in October 2021.In Common Lisp, the function
logcount, given a non-negative integer, returns the number of 1 bits. In either case the integer can be a BIGNUM.Starting in GHC 7.4, the Haskell base package has a
popCount function available on all types that are instances of the Bits class.MySQL version of SQL language provides
BIT_COUNT as a standard function.Fortran 2008 has the standard, intrinsic, elemental function
popcnt returning the number of nonzero bits within an integer.Some programmable scientific pocket calculators feature special commands to calculate the number of set bits, e.g.
#B on the HP-16C.FreePascal implements popcnt since version 3.0.
Processor support
- The IBM STRETCH computer in the 1960s calculated the number of set bits as well as the number of leading zeros as a by-product of all logical operations.
- Cray supercomputers early on featured a population count machine instruction, rumoured to have been specifically requested by the U.S. government National Security Agency for cryptanalysis applications.
- Control Data Corporation's 6000 and Cyber 70/170 series machines included a population count instruction; in COMPASS, this instruction was coded as
CXi. - The 64-bit SPARC version 9 architecture defines a
POPCinstruction, but most implementations do not implement it, requiring it be emulated by the operating system. - Donald Knuth's model computer MMIX that is going to replace MIX in his book The Art of Computer Programming has an
SADDinstruction since 1999.SADD a,b,ccounts all bits that are 1 in b and 0 in c and writes the result to a. - Compaq's Alpha 21264A, released in 1999, was the first Alpha series CPU design that had the count extension.
- Analog Devices' Blackfin processors feature the
ONESinstruction to perform a 32-bit population count. - AMD's Barcelona architecture introduced the advanced bit manipulation ISA introducing the
POPCNTinstruction as part of the SSE4a extensions in 2007. - Intel Core processors introduced a
POPCNTinstruction with the SSE4.2 instruction set extension, first available in a Nehalem-based Core i7 processor, released in November 2008. - The ARM architecture introduced the
VCNTinstruction as part of the Advanced SIMD extensions. - The RISC-V architecture introduced the
CPOPinstruction as part of the Bit Manipulation extension.