// Encode encodes the distance using the parameter l. Dist can have values from // the full range of uint32 values. To get the distance offset the actual match // distance has to be decreased by 1. A distance offset of 0xffffffff (eos) // indicates the end of the stream. func (dc *distCodec) Encode(e *rangeEncoder, dist uint32, l uint32) (err error) { // Compute the posSlot using nlz32 var posSlot uint32 var bits uint32 if dist < startPosModel { posSlot = dist } else { bits = uint32(30 - u32.NLZ(dist)) posSlot = startPosModel - 2 + (bits << 1) posSlot += (dist >> uint(bits)) & 1 } if err = dc.posSlotCodecs[lenState(l)].Encode(e, posSlot); err != nil { return } switch { case posSlot < startPosModel: return nil case posSlot < endPosModel: tc := &dc.posModel[posSlot-startPosModel] return tc.Encode(dist, e) } dic := directCodec(bits - alignBits) if err = dic.Encode(e, dist>>alignBits); err != nil { return } return dc.alignCodec.Encode(dist, e) }
// hashTableExponent derives the hash table exponent from the history length. func hashTableExponent(n uint32) int { e := 30 - u32.NLZ(n) switch { case e < minTableExponent: e = minTableExponent case e > maxTableExponent: e = maxTableExponent } return e }
// distBits returns the number of bits required to encode dist. func distBits(dist uint32) int { if dist < startPosModel { return 6 } // slot s > 3, dist d // s = 2(bits(d)-1) + bit(d, bits(d)-2) // s>>1 = bits(d)-1 // bits(d) = 32-nlz32(d) // s>>1=31-nlz32(d) // n = 5 + (s>>1) = 36 - nlz32(d) return 36 - u32.NLZ(dist) }