public static EncodedUintVector_UInt16 MakeEncodedVector_16(UInt16[] values, Encoder encoder)
        {
            EncodedUintVector.EncodeUintVector(values, encoder);
            var decoder = encoder.Decoder();
            EncodedUintVector_UInt16 actual = new();

            Assert.True(actual.Init(decoder));
            return(actual);
        }
Beispiel #2
0
    // Appends the EncodedStringVector representation to the given Encoder.
    //
    // REQUIRES: "encoder" uses the default constructor, so that its buffer
    //           can be enlarged as necessary by calling Ensure(int).
    public void Encode(Encoder encoder)
    {
        offsets_.Add((ulong)data_.Length());
        // We don't encode the first element of "offsets_", which is always zero.
        var newarr = offsets_.Skip(1).Take(offsets_.Count - 1).ToArray();

        EncodedUintVector.EncodeUintVector(newarr, encoder);
        encoder.Ensure(data_.Length());
        encoder.PutEncoder(data_);
    }
        // TestEncodedUintVector
        public static void TestEncodedUintVector_16(UInt16[] expected, int expected_bytes)
        {
            Encoder encoder = new();

            EncodedUintVector.EncodeUintVector(expected, encoder);
            Assert.Equal(expected_bytes, encoder.Length());
            var decoder = encoder.Decoder();
            EncodedUintVector_UInt16 actual = new();

            Assert.True(actual.Init(decoder));
            Assert.Equal(actual.Decode(), expected);
        }
    // Initializes the EncodedS2CellIdVector.
    //
    // REQUIRES: The Decoder data buffer must outlive this object.
    public bool Init(Decoder decoder)
    {
        // All encodings have at least 2 bytes (one for our header and one for the
        // EncodedUintVector header), so this is safe.
        if (decoder.Avail() < 2)
        {
            return(false);
        }

        // Invert the encoding of (shift_code, base_len) described above.
        int code_plus_len = decoder.Get8();
        int shift_code    = code_plus_len >> 3;

        if (shift_code == 31)
        {
            shift_code = 29 + decoder.Get8();
            if (shift_code > 56)
            {
                return(false);                  // Valid range 0..56
            }
        }

        // Decode the "base_len" most-significant bytes of "base".
        int base_len = code_plus_len & 7;

        if (!EncodedUintVector.DecodeUintWithLength(base_len, decoder, out base_))
        {
            return(false);
        }
        base_ <<= 64 - 8 * Math.Max(1, base_len);

        // Invert the encoding of "shift_code" described above.
        if (shift_code >= 29)
        {
            shift_ = (byte)(2 * (shift_code - 29) + 1);
            base_ |= 1UL << (shift_ - 1);
        }
        else
        {
            shift_ = (byte)(2 * shift_code);
        }
        return(deltas_.Init(decoder));
    }
    // Encodes a vector of S2CellIds in a format that can later be decoded as an
    // EncodedS2CellIdVector.  The S2CellIds do not need to be valid.
    //
    // REQUIRES: "encoder" uses the default constructor, so that its buffer
    //           can be enlarged as necessary by calling Ensure(int).
    public static void EncodeS2CellIdVector(List <S2CellId> v, Encoder encoder)
    {
        // v[i] is encoded as (base + (deltas[i] << shift)).
        //
        // "base" consists of 0-7 bytes, and is always shifted so that its bytes are
        // the most-significant bytes of a UInt64.
        //
        // "deltas" is an EncodedUintVector<UInt64>, which means that all deltas
        // have a fixed-length encoding determined by the largest delta.
        //
        // "shift" is in the range 0..56.  The shift value is odd only if all
        // S2CellIds are at the same level, in which case the bit at position
        // (shift - 1) is automatically set to 1 in "base".
        //
        // "base" (3 bits) and "shift" (6 bits) are encoded in either one or two
        // bytes as follows:
        //
        //   - if (shift <= 4 or shift is even), then 1 byte
        //   - otherwise 2 bytes
        //
        // Note that (shift == 1) means that all S2CellIds are leaf cells, and
        // (shift == 2) means that all S2CellIds are at level 29.
        //
        // The full encoded format is as follows:
        //
        //  Byte 0, bits 0-2: base length (0-7 bytes)
        //  Byte 0, bits 3-7: encoded shift (see below)
        //  Byte 1: extended shift code (only needed for odd shifts >= 5)
        //  Followed by 0-7 bytes of "base"
        //  Followed by an EncodedUintVector of deltas.

        UInt64 v_or  = 0;
        UInt64 v_and = ~0UL;
        UInt64 v_min = ~0UL;
        UInt64 v_max = 0;

        foreach (var cellid in v)
        {
            v_or  |= cellid.Id;
            v_and &= cellid.Id;
            v_min  = Math.Min(v_min, cellid.Id);
            v_max  = Math.Max(v_max, cellid.Id);
        }

        // These variables represent the values that will used during encoding.
        UInt64 e_base          = 0; // Base value.
        int    e_base_len      = 0; // Number of bytes to represent "base".
        int    e_shift         = 0; // Delta shift.
        int    e_max_delta_msb = 0; // Bit position of the MSB of the largest delta.

        if (v_or > 0)
        {
            // We only allow even shifts, unless all values have the same low bit (in
            // which case the shift is odd and the preceding bit is implicitly on).
            // There is no point in allowing shifts > 56 since deltas are encoded in
            // at least 1 byte each.
            e_shift = Math.Min(56, BitsUtils.FindLSBSetNonZero64(v_or) & ~1);
            if ((v_and & (1UL << e_shift)) != 0)
            {
                ++e_shift;                                   // All S2CellIds same level.
            }
            // "base" consists of the "base_len" most significant bytes of the minimum
            // S2CellId.  We consider all possible values of "base_len" (0..7) and
            // choose the one that minimizes the total encoding size.
            UInt64 e_bytes = ~0UL;  // Best encoding size so far.
            for (int len = 0; len < 8; ++len)
            {
                // "t_base" is the base value being tested (first "len" bytes of v_min).
                // "t_max_delta_msb" is the most-significant bit position of the largest
                // delta (or zero if there are no deltas, i.e. if v.size() == 0).
                // "t_bytes" is the total size of the variable portion of the encoding.
                UInt64 t_base          = v_min & ~(~0UL >> (8 * len));
                int    t_max_delta_msb = Math.Max(0, BitsUtils.Log2Floor64((v_max - t_base) >> e_shift));
                UInt64 t_bytes         = (ulong)(len + v.Count * ((t_max_delta_msb >> 3) + 1));
                if (t_bytes < e_bytes)
                {
                    e_base          = t_base;
                    e_base_len      = len;
                    e_max_delta_msb = t_max_delta_msb;
                    e_bytes         = t_bytes;
                }
            }

            // It takes one extra byte to encode odd shifts (i.e., the case where all
            // S2CellIds are at the same level), so check whether we can get the same
            // encoding size per delta using an even shift.
            if (((e_shift & 1) != 0) && (e_max_delta_msb & 7) != 7)
            {
                --e_shift;
            }
        }

        System.Diagnostics.Debug.Assert(e_base_len <= 7);
        System.Diagnostics.Debug.Assert(e_shift <= 56);
        encoder.Ensure(2 + e_base_len);

        // As described above, "shift" and "base_len" are encoded in 1 or 2 bytes.
        // "shift_code" is 5 bits:
        //   values <= 28 represent even shifts in the range 0..56
        //   values 29, 30 represent odd shifts 1 and 3
        //   value 31 indicates that the shift is odd and encoded in the next byte
        int shift_code = e_shift >> 1;

        if ((e_shift & 1) != 0)
        {
            shift_code = Math.Min(31, shift_code + 29);
        }
        encoder.Put8((byte)((shift_code << 3) | e_base_len));
        if (shift_code == 31)
        {
            encoder.Put8((byte)(e_shift >> 1));  // Shift is always odd, so 3 bits unused.
        }
        // Encode the "base_len" most-significant bytes of "base".
        UInt64 base_bytes = e_base >> (64 - 8 * Math.Max(1, e_base_len));

        EncodedUintVector.EncodeUintWithLength(base_bytes, e_base_len, encoder);

        // Finally, encode the vector of deltas.
        var deltas = new UInt64[v.Count];

        for (var i = 0; i < v.Count; i++)
        {
            var cellid = v[i];
            deltas[i] = (cellid.Id - e_base) >> e_shift;
        }
        EncodedUintVector.EncodeUintVector(deltas, encoder);
    }