func (d *digest) pad() {
	offset := d.absorbed % d.rate()
	padOpenLane := offset / laneSize
	d.a[padOpenLane] ^= 0x0000000000000001 << uint(8*(offset%laneSize))
	padCloseLane := (d.rate() / laneSize) - 1
	d.a[padCloseLane] ^= 0x8000000000000000
}
pad computes the SHA3 padding scheme based on the number of bytes absorbed.
The padding is a 1 bit, followed by an arbitrary number of 0s and then a final 1 bit, such that
the input bits plus padding bits are a multiple of rate(). Adding the padding simply requires
xoring an opening and closing bit into the appropriate lanes.
package sha3
import (
	"encoding/binary"
	"hash"
)
const laneSize = 8
const sliceSize = 5
const numLanes = sliceSize * sliceSize
const stateSize = laneSize * numLanes
type digest struct {
	a          [numLanes]uint64  
	outputSize int               
	capacity   int               
	absorbed   int               
}
func minInt(v1, v2 int) int {
	if v1 <= v2 {
		return v1
	}
	return v2
}
func (d *digest) rate() int {
	return stateSize - d.capacity
}
func (d *digest) Reset() {
	d.absorbed = 0
	for i := range d.a {
		d.a[i] = 0
	}
}
func (d *digest) BlockSize() int { return d.rate() }
func (d *digest) Size() int {
	return d.outputSize
}
func (d *digest) unalignedAbsorb(p []byte) {
	var t uint64
	for i := len(p) - 1; i >= 0; i-- {
		t <<= 8
		t |= uint64(p[i])
	}
	offset := (d.absorbed) % d.rate()
	t <<= 8 * uint(offset%laneSize)
	d.a[offset/laneSize] ^= t
	d.absorbed += len(p)
}
func (d *digest) Write(p []byte) (int, error) {
	offset := d.absorbed % d.rate()
	toWrite := len(p)
	if (offset%laneSize != 0 || len(p) < 8) && len(p) > 0 {
		toAbsorb := minInt(laneSize-(offset%laneSize), len(p))
		d.unalignedAbsorb(p[:toAbsorb])
		p = p[toAbsorb:]
		offset = (d.absorbed) % d.rate()
		if (d.absorbed)%d.rate() == 0 {
			keccakF(&d.a)
		}
	}
	for len(p) > 7 {
		firstLane := offset / laneSize
		lastLane := minInt(d.rate()/laneSize, firstLane+len(p)/laneSize)
		for lane := firstLane; lane < lastLane; lane++ {
			d.a[lane] ^= binary.LittleEndian.Uint64(p[:laneSize])
			p = p[laneSize:]
		}
		d.absorbed += (lastLane - firstLane) * laneSize
		if (d.absorbed)%d.rate() == 0 {
			keccakF(&d.a)
		}
		offset = 0
	}
	if len(p) > 0 {
		d.unalignedAbsorb(p)
	}
	return toWrite, nil
}