github.com/apache/arrow/go/v14@v14.0.1/internal/bitutils/bitmap_generate.go (about) 1 // Licensed to the Apache Software Foundation (ASF) under one 2 // or more contributor license agreements. See the NOTICE file 3 // distributed with this work for additional information 4 // regarding copyright ownership. The ASF licenses this file 5 // to you under the Apache License, Version 2.0 (the 6 // "License"); you may not use this file except in compliance 7 // with the License. You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package bitutils 18 19 import "github.com/apache/arrow/go/v14/arrow/bitutil" 20 21 // GenerateBits writes sequential bits to a bitmap. Bits preceding the 22 // initial start offset are preserved, bits following the bitmap may 23 // get clobbered. 24 func GenerateBits(bitmap []byte, start, length int64, g func() bool) { 25 if length == 0 { 26 return 27 } 28 29 cur := bitmap[start/8:] 30 mask := bitutil.BitMask[start%8] 31 curbyte := cur[0] & bitutil.PrecedingBitmask[start%8] 32 33 for i := int64(0); i < length; i++ { 34 bit := g() 35 if bit { 36 curbyte = curbyte | mask 37 } 38 mask <<= 1 39 if mask == 0 { 40 mask = 1 41 cur[0] = curbyte 42 cur = cur[1:] 43 curbyte = 0 44 } 45 } 46 47 if mask != 1 { 48 cur[0] = curbyte 49 } 50 } 51 52 // GenerateBitsUnrolled is like GenerateBits but unrolls its main loop for 53 // higher performance. 54 // 55 // See the benchmarks for evidence. 56 func GenerateBitsUnrolled(bitmap []byte, start, length int64, g func() bool) { 57 if length == 0 { 58 return 59 } 60 61 var ( 62 curbyte byte 63 cur = bitmap[start/8:] 64 startBitOffset uint64 = uint64(start % 8) 65 mask = bitutil.BitMask[startBitOffset] 66 remaining = length 67 ) 68 69 if mask != 0x01 { 70 curbyte = cur[0] & bitutil.PrecedingBitmask[startBitOffset] 71 for mask != 0 && remaining > 0 { 72 if g() { 73 curbyte |= mask 74 } 75 mask <<= 1 76 remaining-- 77 } 78 cur[0] = curbyte 79 cur = cur[1:] 80 } 81 82 var outResults [8]byte 83 for remainingBytes := remaining / 8; remainingBytes > 0; remainingBytes-- { 84 for i := 0; i < 8; i++ { 85 if g() { 86 outResults[i] = 1 87 } else { 88 outResults[i] = 0 89 } 90 } 91 cur[0] = (outResults[0] | outResults[1]<<1 | outResults[2]<<2 | 92 outResults[3]<<3 | outResults[4]<<4 | outResults[5]<<5 | 93 outResults[6]<<6 | outResults[7]<<7) 94 cur = cur[1:] 95 } 96 97 remainingBits := remaining % 8 98 if remainingBits > 0 { 99 curbyte = 0 100 mask = 0x01 101 for ; remainingBits > 0; remainingBits-- { 102 if g() { 103 curbyte |= mask 104 } 105 mask <<= 1 106 } 107 cur[0] = curbyte 108 } 109 }