public static void DecodeQuintBlock(
            ref BitStream128 bitStream,
            ref IntegerSequence listIntegerEncoded,
            int numberBitsPerValue)
        {
            ReadOnlySpan <byte> interleavedBits = new byte[] { 3, 2, 2 };

            // Implement the algorithm in section C.2.12
            Span <int> m               = stackalloc int[3];
            ulong      encoded         = 0;
            int        encodedBitsRead = 0;

            for (int i = 0; i < m.Length; i++)
            {
                m[i] = bitStream.ReadBits(numberBitsPerValue);

                uint encodedBits = (uint)bitStream.ReadBits(interleavedBits[i]);

                encoded         |= encodedBits << encodedBitsRead;
                encodedBitsRead += interleavedBits[i];
            }

            ReadOnlySpan <byte> encodings = GetQuintEncoding((int)encoded);

            for (int i = 0; i < 3; i++)
            {
                IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Quint, numberBitsPerValue)
                {
                    BitValue   = m[i],
                    QuintValue = encodings[i]
                };

                listIntegerEncoded.Add(ref intEncoded);
            }
        }
        public static void DecodeTritBlock(
            ref BitStream128 bitStream,
            ref IntegerSequence listIntegerEncoded,
            int numberBitsPerValue)
        {
            // Implement the algorithm in section C.2.12
            Span <int> m = stackalloc int[5];

            m[0] = bitStream.ReadBits(numberBitsPerValue);
            int encoded = bitStream.ReadBits(2);

            m[1]     = bitStream.ReadBits(numberBitsPerValue);
            encoded |= bitStream.ReadBits(2) << 2;
            m[2]     = bitStream.ReadBits(numberBitsPerValue);
            encoded |= bitStream.ReadBits(1) << 4;
            m[3]     = bitStream.ReadBits(numberBitsPerValue);
            encoded |= bitStream.ReadBits(2) << 5;
            m[4]     = bitStream.ReadBits(numberBitsPerValue);
            encoded |= bitStream.ReadBits(1) << 7;

            ReadOnlySpan <byte> encodings = GetTritEncoding(encoded);

            IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue);

            for (int i = 0; i < 5; i++)
            {
                intEncoded.BitValue  = m[i];
                intEncoded.TritValue = encodings[i];

                listIntegerEncoded.Add(ref intEncoded);
            }
        }
        public static void DecodeIntegerSequence(
            ref IntegerSequence decodeIntegerSequence,
            ref BitStream128 bitStream,
            int maxRange,
            int numberValues)
        {
            // Determine encoding parameters
            IntegerEncoded intEncoded = CreateEncoding(maxRange);

            // Start decoding
            int numberValuesDecoded = 0;

            while (numberValuesDecoded < numberValues)
            {
                switch (intEncoded.GetEncoding())
                {
                case EIntegerEncoding.Quint:
                {
                    DecodeQuintBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
                    numberValuesDecoded += 3;

                    break;
                }

                case EIntegerEncoding.Trit:
                {
                    DecodeTritBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
                    numberValuesDecoded += 5;

                    break;
                }

                case EIntegerEncoding.JustBits:
                {
                    intEncoded.BitValue = bitStream.ReadBits(intEncoded.NumberBits);
                    decodeIntegerSequence.Add(ref intEncoded);
                    numberValuesDecoded++;

                    break;
                }
                }
            }
        }