// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bitutil

import (
	
	
	

	
)

var (
	BitMask        = [8]byte{1, 2, 4, 8, 16, 32, 64, 128}
	FlippedBitMask = [8]byte{254, 253, 251, 247, 239, 223, 191, 127}
)

// IsMultipleOf8 returns whether v is a multiple of 8.
func ( int64) bool { return &7 == 0 }

// IsMultipleOf64 returns whether v is a multiple of 64
func ( int64) bool { return &63 == 0 }

func ( int64) int64 { return ( + 7) >> 3 }

// NextPowerOf2 rounds x to the next power of two.
func ( int) int { return 1 << uint(bits.Len(uint())) }

// CeilByte rounds size to the next multiple of 8.
func ( int) int { return ( + 7) &^ 7 }

// CeilByte64 rounds size to the next multiple of 8.
func ( int64) int64 { return ( + 7) &^ 7 }

// BitIsSet returns true if the bit at index i in buf is set (1).
func ( []byte,  int) bool { return ([uint()/8] & BitMask[byte()%8]) != 0 }

// BitIsNotSet returns true if the bit at index i in buf is not set (0).
func ( []byte,  int) bool { return ([uint()/8] & BitMask[byte()%8]) == 0 }

// SetBit sets the bit at index i in buf to 1.
func ( []byte,  int) { [uint()/8] |= BitMask[byte()%8] }

// ClearBit sets the bit at index i in buf to 0.
func ( []byte,  int) { [uint()/8] &= FlippedBitMask[byte()%8] }

// SetBitTo sets the bit at index i in buf to val.
func ( []byte,  int,  bool) {
	if  {
		SetBit(, )
	} else {
		ClearBit(, )
	}
}

// CountSetBits counts the number of 1's in buf up to n bits.
func ( []byte, ,  int) int {
	if  > 0 {
		return countSetBitsWithOffset(, , )
	}

	 := 0

	 :=  / uint64SizeBits * 8
	for ,  := range bytesToUint64([:]) {
		 += bits.OnesCount64()
	}

	for ,  := range [ : /8] {
		 += bits.OnesCount8()
	}

	// tail bits
	for  :=  &^ 0x7;  < ; ++ {
		if BitIsSet(, ) {
			++
		}
	}

	return 
}

func countSetBitsWithOffset( []byte, ,  int) int {
	 := 0

	 := 
	 := roundUp(, uint64SizeBits)

	 := min(, -)
	for  := ;  < +; ++ {
		if BitIsSet(, ) {
			++
		}
	}

	 := BytesForBits(int64( + ))
	return  + CountSetBits([:], 0, -)
}

func roundUp(,  int) int {
	return ( + ( - 1)) /  * 
}

func min(,  int) int {
	if  <  {
		return 
	}
	return 
}

const (
	uint64SizeBytes = int(unsafe.Sizeof(uint64(0)))
	uint64SizeBits  = uint64SizeBytes * 8
)

var (
	// PrecedingBitmask is a convenience set of values as bitmasks for checking
	// prefix bits of a byte
	PrecedingBitmask = [8]byte{0, 1, 3, 7, 15, 31, 63, 127}
	// TrailingBitmask is the bitwise complement version of kPrecedingBitmask
	TrailingBitmask = [8]byte{255, 254, 252, 248, 240, 224, 192, 128}
)

// SetBitsTo is a convenience function to quickly set or unset all the bits
// in a bitmap starting at startOffset for length bits.
func ( []byte, ,  int64,  bool) {
	if  == 0 {
		return
	}

	 := 
	 :=  + 
	var  uint8 = 0
	if  {
		 = math.MaxUint8
	}

	 :=  / 8
	 := /8 + 1

	// don't modify bits before the startOffset by using this mask
	 := PrecedingBitmask[%8]
	// don't modify bits past the length by using this mask
	 := TrailingBitmask[%8]

	if  == +1 {
		// set bits within a single byte
		 := 
		if %8 != 0 {
			 =  | 
		}

		[] &= 
		[] |=  &^ 
		return
	}

	// set/clear trailing bits of first byte
	[] &= 
	[] |=  &^ 

	if - > 2 {
		memory.Set([+1:-1], )
	}

	if %8 == 0 {
		return
	}

	[-1] &= 
	[-1] |=  &^ 
}