@ -183,29 +183,36 @@ func isWholeWhenMultiplied(in float64) bool {
return in == out
return in == out
}
}
// putCustomBound writes the custom bound to the bstream. It stores values from 0 to
// putCustomBound writes a custom bound to the bstream. It stores values from
// 16.382 (inclusive) that are multiples of 0.001 in an unsigned var int of up to 2 bytes,
// 0 to 33554.430 (inclusive) that are multiples of 0.001 in unsigned varbit
// but needs 1 bit + 8 bytes for other values like negative numbers, numbers greater than
// encoding of up to 4 bytes, but needs 1 bit + 8 bytes for other values like
// 16.382, or numbers that are not a multiple of 0.001, on the assumption that they are
// negative numbers, numbers greater than 33554.430, or numbers that are not
// less common. In detail:
// a multiple of 0.001, on the assumption that they are less common. In detail:
// - Multiply the bound by 1000, without rounding.
// - Multiply the bound by 1000, without rounding.
// - If the multiplied bound is >= 0, <= 16382 and a whole number, store it as an
// - If the multiplied bound is >= 0, <= 33554430 and a whole number,
// unsigned var int.
// add 1 and store it in unsigned varbit encoding. All these numbers are
// - Otherwise, store 0 as an unsigned var int, followed by the 8 bytes of the original
// greater than 0, so the leading bit of the varbit is always 1!
// - Otherwise, store a 0 bit, followed by the 8 bytes of the original
// bound as a float64.
// bound as a float64.
//
// When reading the values, we can first decode a value as unsigned varbit,
// if it's 0, then we read the next 8 bytes as a float64, otherwise
// we can convert the value to a float64 by subtracting 1 and dividing by 1000.
func putCustomBound ( b * bstream , f float64 ) {
func putCustomBound ( b * bstream , f float64 ) {
tf := f * 1000
tf := f * 1000
if tf < 0 || tf > 16382 || ! isWholeWhenMultiplied ( f ) {
// 33554431-1 comes from the maximum that can be stored in a varint in 4
b . putUvarint ( 0 )
// bytes, other values are stored in 8 bytes anyway.
if tf < 0 || tf > 33554430 || ! isWholeWhenMultiplied ( f ) {
b . writeBit ( zero )
b . writeBits ( math . Float64bits ( f ) , 64 )
b . writeBits ( math . Float64bits ( f ) , 64 )
return
return
}
}
b . putUvarint ( uint64 ( math . Round ( tf ) + 1 ) )
putVarbitUint ( b , uint64 ( math . Round ( tf ) ) + 1 )
}
}
// readCustomBound reads the custom bound written with putCustomBound.
// readCustomBound reads the custom bound written with putCustomBound.
func readCustomBound ( br * bstreamReader ) ( float64 , error ) {
func readCustomBound ( br * bstreamReader ) ( float64 , error ) {
b , err := br . readUvarint ( )
b , err := readVarbitUint ( br )
if err != nil {
if err != nil {
return 0 , err
return 0 , err
}
}