public void SliceArray()
        {
            var source   = new QArray <long>(0);
            var range    = new QRange(0, 0);
            var expected = new QArray <long>(0);
            var actual   = source.Slice(range);

            Assert.Equal(expected, actual);

            source   = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
            range    = new QRange(0, 2, 10);
            expected = new QArray <long>(0, 2, 4, 6, 8, 10);
            actual   = source.Slice(range);
            Assert.Equal(expected, actual);


            source   = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
            expected = new QArray <long>(1, 6);
            actual   = source.Slice(new QRange(1, 5, 10));
            Assert.Equal(expected, actual);

            OperationsTestHelper.IgnoreDebugAssert(() =>
            {
                source   = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
                range    = null;
                expected = new QArray <long>();
                actual   = source.Slice(range);
                Assert.Equal(expected, actual);
            });
        }
        public void ArrayEnumeration()
        {
            // Basic enumeration
            var array1 = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            int index  = 0;

            foreach (var n in array1)
            {
                Assert.Equal(index, n);
                index++;
            }
            Assert.Equal(10, index);

            // Enumerating a slice
            var r      = new QRange(1, 2, 10);
            var array2 = array1.Slice(r);

            index = 1;
            foreach (var n in array2)
            {
                Assert.Equal(index, n);
                index += 2;
            }
            Assert.Equal(11, index);

            // Enumerating a join
            var array3 = QArray <long> .Add(array1, array2);

            index = 0;
            foreach (var n in array3)
            {
                if (index < 10)
                {
                    Assert.Equal(index, n);
                }
                else
                {
                    Assert.Equal(2 * index - 19, n);
                }
                index++;
            }
            Assert.Equal(15, index);
        }
        public void ArraySharing()
        {
            // Basic copy-on-write
            var array1 = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            var array2 = new QArray <long>(array1);

            Assert.Equal(2, array1[2]);
            Assert.Equal(2, array2[2]);
            array1.Modify(2, 12);
            Assert.Equal(12, array1[2]);
            Assert.Equal(2, array2[2]);
            array2.Modify(2, 22);
            Assert.Equal(12, array1[2]);
            Assert.Equal(22, array2[2]);

            // Arrays of arrays
            array1 = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            array2 = new QArray <long>(array1);
            var arrayArray1 = new QArray <QArray <long> >(array1, array2); // in generated C# code, QArray<IQArray<long>> is used
            var arrayArray2 = new QArray <QArray <long> >(arrayArray1);

            Assert.Equal(2, arrayArray1[0][2]);
            Assert.Equal(2, arrayArray1[1][2]);
            arrayArray1.Modify(0, arrayArray1[0].Modify(2, 12));
            Assert.Equal(12, arrayArray1[0][2]);
            Assert.Equal(2, arrayArray1[1][2]);
            Assert.Equal(12, array1[2]);
            arrayArray1.Modify(1, arrayArray1[1].Modify(2, 22));
            Assert.Equal(12, arrayArray1[0][2]);
            Assert.Equal(22, arrayArray1[1][2]);
            Assert.Equal(12, array1[2]);
            Assert.Equal(22, array2[2]);

            // Copy-on-write with slices
            var r        = new QRange(1, 2, 10);
            var array3   = array2.Slice(r);
            var expected = new QArray <long>(1, 3, 5, 7, 9);

            Assert.Equal(expected, array3);
            array3.Modify(0, 11);
            Assert.Equal(1, array2[1]);
            Assert.Equal(11, array3[0]);

            // Mixing slicing and joining
            array2 = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
            var expected2 = new QArray <long>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

            r      = new QRange(1, 2, 10);
            array3 = array2.Slice(r);
            var array4 = new QArray <long>(11, 13);
            var array5 = QArray <long> .Add(array3, array4);

            var expected3 = new QArray <long>(1, 3, 5, 7, 9);
            var expected4 = new QArray <long>(11, 13);
            var expected5 = new QArray <long>(1, 3, 5, 7, 9, 11, 13);

            Assert.Equal(expected2, array2);
            Assert.Equal(expected3, array3);
            Assert.Equal(expected4, array4);
            Assert.Equal(expected5, array5);

            // Self-joining
            array1 = new QArray <long>(0, 1, 2);
            array2 = new QArray <long>(QArray <long> .Add(array1, array1));
            var expected1 = new QArray <long>(0, 1, 2);

            expected2 = new QArray <long>(0, 1, 2, 0, 1, 2);
            Assert.Equal(expected1, array1);
            Assert.Equal(expected2, array2);
            array1.Modify(0, 10);
            Assert.Equal(10, array1[0]);
            Assert.Equal(0, array2[0]);
        }