github.com/primecitizens/pcz/std@v0.2.1/core/bits/zeros.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 // LeadingZeros returns the number of leading zero bits in x; the result is UintSize for x == 0. 15 func LeadingZeros(x uint) int { return arch.UintBits - Len(x) } 16 17 // LeadingZeros8 returns the number of leading zero bits in x; the result is 8 for x == 0. 18 func LeadingZeros8(x uint8) int { return 8 - Len8(x) } 19 20 // LeadingZeros16 returns the number of leading zero bits in x; the result is 16 for x == 0. 21 func LeadingZeros16(x uint16) int { return 16 - Len16(x) } 22 23 // LeadingZeros32 returns the number of leading zero bits in x; the result is 32 for x == 0. 24 func LeadingZeros32(x uint32) int { return 32 - Len32(x) } 25 26 // LeadingZeros64 returns the number of leading zero bits in x; the result is 64 for x == 0. 27 func LeadingZeros64(x uint64) int { return 64 - Len64(x) } 28 29 // See http://supertech.csail.mit.edu/papers/debruijn.pdf 30 const ( 31 DeBruijn32 = 0x077CB531 32 DeBruijn32Table = "" + 33 "\x00\x01\x28\x02\x29\x14\x24\x03\x30\x22\x20\x15\x25\x17\x04\x08" + 34 "\x31\x27\x13\x23\x21\x19\x16\x07\x26\x12\x18\x06\x11\x05\x10\x09" 35 ) 36 37 const ( 38 DeBruijn64 = 0x03f79d71b4ca8b09 39 DeBruijn64Table = "" + 40 "\x00\x01\x56\x02\x57\x49\x28\x03\x61\x58\x42\x50\x38\x29\x17\x04" + 41 "\x62\x47\x59\x36\x45\x43\x51\x22\x53\x39\x33\x30\x24\x18\x12\x05" + 42 "\x63\x55\x48\x27\x60\x41\x37\x16\x46\x35\x44\x21\x52\x32\x23\x11" + 43 "\x54\x26\x40\x15\x34\x20\x31\x10\x25\x14\x19\x09\x13\x08\x07\x06" 44 ) 45 46 // TrailingZeros returns the number of trailing zero bits in x; the result is UintSize for x == 0. 47 func TrailingZeros(x uint) int { 48 if arch.UintBits == 32 { 49 return TrailingZeros32(uint32(x)) 50 } 51 return TrailingZeros64(uint64(x)) 52 } 53 54 const Ntz8Table = "" + 55 "\x08\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 56 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 57 "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 58 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 59 "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 60 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 61 "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 62 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 63 "\x07\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 64 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 65 "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 66 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 67 "\x06\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 68 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 69 "\x05\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" + 70 "\x04\x00\x01\x00\x02\x00\x01\x00\x03\x00\x01\x00\x02\x00\x01\x00" 71 72 // TrailingZeros8 returns the number of trailing zero bits in x; the result is 8 for x == 0. 73 func TrailingZeros8(x uint8) int { 74 return int(Ntz8Table[x]) 75 } 76 77 // TrailingZeros16 returns the number of trailing zero bits in x; the result is 16 for x == 0. 78 func TrailingZeros16(x uint16) int { 79 if x == 0 { 80 return 16 81 } 82 // see comment in TrailingZeros64 83 return int(DeBruijn32Table[uint32(x&-x)*DeBruijn32>>(32-5)]) 84 } 85 86 // TrailingZeros32 returns the number of trailing zero bits in x; the result is 32 for x == 0. 87 func TrailingZeros32(x uint32) int { 88 if x == 0 { 89 return 32 90 } 91 // see comment in TrailingZeros64 92 return int(DeBruijn32Table[(x&-x)*DeBruijn32>>(32-5)]) 93 } 94 95 // TrailingZeros64 returns the number of trailing zero bits in x; the result is 64 for x == 0. 96 func TrailingZeros64(x uint64) int { 97 if x == 0 { 98 return 64 99 } 100 // If popcount is fast, replace code below with return popcount(^x & (x - 1)). 101 // 102 // x & -x leaves only the right-most bit set in the word. Let k be the 103 // index of that bit. Since only a single bit is set, the value is two 104 // to the power of k. Multiplying by a power of two is equivalent to 105 // left shifting, in this case by k bits. The de Bruijn (64 bit) constant 106 // is such that all six bit, consecutive substrings are distinct. 107 // Therefore, if we have a left shifted version of this constant we can 108 // find by how many bits it was shifted by looking at which six bit 109 // substring ended up at the top of the word. 110 // (Knuth, volume 4, section 7.3.1) 111 return int(DeBruijn64Table[(x&-x)*DeBruijn64>>(64-6)]) 112 }