public void TestBasic1()
        {
            var freqs   = new uint[] { 10, 30, 10 }; // Symbol 0 occurs 10x, symbol 1 occurs 30x, symbol 2 occurs 10x
            var ms      = new MemoryStream();
            var context = new ArithmeticSymbolArrayContext(freqs);
            var encoder = new ArithmeticCodingWriter(ms, context);

            for (int i = 0; i < 10; i++)
            {
                encoder.WriteSymbol(1);
                encoder.WriteSymbol(0);
                encoder.WriteSymbol(1);
                encoder.WriteSymbol(2);
                encoder.WriteSymbol(1);
            }
            encoder.Finalize();
            ms.WriteByte(47);

            ms = new MemoryStream(ms.ToArray());
            var decoder = new ArithmeticCodingReader(ms, context);

            for (int i = 0; i < 10; i++)
            {
                Assert.AreEqual(1, decoder.ReadSymbol());
                Assert.AreEqual(0, decoder.ReadSymbol());
                Assert.AreEqual(1, decoder.ReadSymbol());
                Assert.AreEqual(2, decoder.ReadSymbol());
                Assert.AreEqual(1, decoder.ReadSymbol());
            }
            decoder.Finalize();
            Assert.AreEqual(47, ms.ReadByte());
        }
        public void TestArrayContext()
        {
            int count = 1000;
            var ctx   = new ArithmeticSymbolArrayContext(count);

            Assert.AreEqual(0UL, ctx.GetSymbolFrequency(-1000));
            Assert.AreEqual(0UL, ctx.GetSymbolFrequency(-1));
            Assert.AreEqual(1UL, ctx.GetSymbolFrequency(0));
            Assert.AreEqual(1UL, ctx.GetSymbolFrequency(1));
            Assert.AreEqual(0UL, ctx.GetSymbolPosition(0));
            Assert.AreEqual(1UL, ctx.GetSymbolPosition(1));
            Assert.AreEqual(1UL, ctx.GetSymbolFrequency(count - 1));
            Assert.AreEqual(0UL, ctx.GetSymbolFrequency(count));
            Assert.AreEqual(0UL, ctx.GetSymbolFrequency(count + 1000));

            ctx = new ArithmeticSymbolArrayContext(new uint[] { 1, 1, 1, 1 });
            ctx.SetSymbolFrequency(1, 5);
            ctx.SetSymbolFrequency(3, 5);
            Assert.AreEqual(6UL, ctx.GetSymbolPosition(2));
        }
        public void TestAdvanced()
        {
            _rnd = new Random(12345);
            int max     = 1000;
            var symbols = Enumerable.Range(1, 100_000).Select(_ => _rnd.Next(0, max)).ToArray();

            var mainContext      = new ArithmeticSymbolArrayContext(max, _ => 1);
            var secondaryContext = new ArithmeticSymbolArrayContext(new uint[] { 3, 2, 1 });

            var ms      = new MemoryStream();
            var encoder = new ArithmeticCodingWriter(ms, mainContext);

            writeInt(ms, 12345);
            for (int i = 0; i < symbols.Length; i++)
            {
                encoder.WriteSymbol(symbols[i]);
                mainContext.IncrementSymbolFrequency(symbols[i]);
                encoder.SetContext(mainContext);
                if (i % 1000 == 999)
                {
                    encoder.SetContext(secondaryContext);
                    encoder.WriteSymbol(0);
                    encoder.WriteSymbol(1);
                    encoder.WriteSymbol(0);
                    encoder.WriteSymbol(1);
                    encoder.WriteSymbol(0);
                    encoder.WriteSymbol(2);
                    encoder.SetContext(mainContext);
                }
            }
            encoder.Finalize(false);
            writeInt(ms, -54321); // to verify that the stream ends where we think it ends
            var encoded = ms.ToArray();


            ms          = new MemoryStream(encoded);
            mainContext = new ArithmeticSymbolArrayContext(max, _ => 1); // reset frequencies
            Assert.AreEqual(12345, readInt(ms));
            var decoder = new ArithmeticCodingReader(ms, mainContext);

            for (int i = 0; i < symbols.Length; i++)
            {
                var sym = decoder.ReadSymbol();
                Assert.AreEqual(symbols[i], sym);
                mainContext.IncrementSymbolFrequency(sym);
                decoder.SetContext(mainContext);
                if (i % 1000 == 999)
                {
                    decoder.SetContext(secondaryContext);
                    Assert.AreEqual(0, decoder.ReadSymbol());
                    Assert.AreEqual(1, decoder.ReadSymbol());
                    Assert.AreEqual(0, decoder.ReadSymbol());
                    Assert.AreEqual(1, decoder.ReadSymbol());
                    Assert.AreEqual(0, decoder.ReadSymbol());
                    Assert.AreEqual(2, decoder.ReadSymbol());
                    decoder.SetContext(mainContext);
                }
            }
            decoder.Finalize(false);
            Assert.AreEqual(-54321, readInt(ms));
        }