github.com/primecitizens/pcz/std@v0.2.1/core/bits/ones.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright 2023 The Prime Citizens 3 // 4 // Copyright 2017 The Go Authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file. 7 8 package bits 9 10 import ( 11 "github.com/primecitizens/pcz/std/core/arch" 12 ) 13 14 const ( 15 m0 = 0x5555555555555555 // 01010101 ... 16 m1 = 0x3333333333333333 // 00110011 ... 17 m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... 18 m3 = 0x00ff00ff00ff00ff // etc. 19 m4 = 0x0000ffff0000ffff 20 ) 21 22 // OnesCount returns the number of one bits ("population count") in x. 23 func OnesCount(x uint) int { 24 if arch.UintBits == 32 { 25 return OnesCount32(uint32(x)) 26 } 27 return OnesCount64(uint64(x)) 28 } 29 30 const Pop8Table = "" + 31 "\x00\x01\x01\x02\x01\x02\x02\x03\x01\x02\x02\x03\x02\x03\x03\x04" + 32 "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + 33 "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + 34 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 35 "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + 36 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 37 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 38 "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + 39 "\x01\x02\x02\x03\x02\x03\x03\x04\x02\x03\x03\x04\x03\x04\x04\x05" + 40 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 41 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 42 "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + 43 "\x02\x03\x03\x04\x03\x04\x04\x05\x03\x04\x04\x05\x04\x05\x05\x06" + 44 "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + 45 "\x03\x04\x04\x05\x04\x05\x05\x06\x04\x05\x05\x06\x05\x06\x06\x07" + 46 "\x04\x05\x05\x06\x05\x06\x06\x07\x05\x06\x06\x07\x06\x07\x07\x08" 47 48 // OnesCount8 returns the number of one bits ("population count") in x. 49 func OnesCount8(x uint8) int { 50 return int(Pop8Table[x]) 51 } 52 53 // OnesCount16 returns the number of one bits ("population count") in x. 54 func OnesCount16(x uint16) int { 55 return int(Pop8Table[x>>8] + Pop8Table[x&0xff]) 56 } 57 58 // OnesCount32 returns the number of one bits ("population count") in x. 59 func OnesCount32(x uint32) int { 60 return int(Pop8Table[x>>24] + Pop8Table[x>>16&0xff] + Pop8Table[x>>8&0xff] + Pop8Table[x&0xff]) 61 } 62 63 // OnesCount64 returns the number of one bits ("population count") in x. 64 func OnesCount64(x uint64) int { 65 // Implementation: Parallel summing of adjacent bits. 66 // See "Hacker's Delight", Chap. 5: Counting Bits. 67 // The following pattern shows the general approach: 68 // 69 // x = x>>1&(m0&m) + x&(m0&m) 70 // x = x>>2&(m1&m) + x&(m1&m) 71 // x = x>>4&(m2&m) + x&(m2&m) 72 // x = x>>8&(m3&m) + x&(m3&m) 73 // x = x>>16&(m4&m) + x&(m4&m) 74 // x = x>>32&(m5&m) + x&(m5&m) 75 // return int(x) 76 // 77 // Masking (& operations) can be left away when there's no 78 // danger that a field's sum will carry over into the next 79 // field: Since the result cannot be > 64, 8 bits is enough 80 // and we can ignore the masks for the shifts by 8 and up. 81 // Per "Hacker's Delight", the first line can be simplified 82 // more, but it saves at best one instruction, so we leave 83 // it alone for clarity. 84 const m = 1<<64 - 1 85 x = x>>1&(m0&m) + x&(m0&m) 86 x = x>>2&(m1&m) + x&(m1&m) 87 x = (x>>4 + x) & (m2 & m) 88 x += x >> 8 89 x += x >> 16 90 x += x >> 32 91 return int(x) & (1<<7 - 1) 92 }