@pengr7 Your solution is very fast and performant, I like it a lot!!! In my original solution I used bitwise shift operator and counted 1s when they became LSB. Which turns out to be the slowest solution of all because number of operations is quite large (when your numbers are big).
Firstly, m1, m2, m3 could be written in binary form as: 01010101..., 00110011...., 0000111100001111.... In fact ,we could add more m according to the same rules.
This part of code
(z & m1) + ((z >> 1) & m1)
could be break into three steps:
store all digits with odd index(right to left), for example, (1011 & m1) will get (0001),
similarly, store all digits with even index((1011 >> 1) & m1) will get (0101)
add them together: (0001 + 0101 = 0110). Divide 0110 into : (01 10) and change them into decimal: (1 2)
We could regard (z & m1) + ((z >> 1) & m1) as a "folding" function. Regard the original digit as an array of 1-digit, binary numbers: [1, 0, 0, 1] , the folder will change the original array into 2-digit, binary numbers: [01(1), 10(2)].
Similarly, folder functions also use m2, m3.... By applying the folder function simutaniously, the array will become 4-digit, 8-digit...until reach any sufficiently large number of digit (sorry for my english but hope you could understand). Finally it will be folded into an array with only one element, which is the result of Hamming distance.