Beispiel #1
0
 public void ChunkedArray_creates_appropriate_number_of_chunks()
 {
     int size = 16 * 1024 * 4 + 100;
     int chunkCount = (int)Math.Ceiling((double)size * sizeof(int) / (16 * 1024));
     var array = new ChunkedArray<int>(size);
     Assert.AreEqual(chunkCount, array.ChunkCount);
 }
Beispiel #2
0
        public void ChunkedArray_reports_proper_length()
        {
            var length = 16 * 1024 * 4 + 100;
            var array  = new ChunkedArray <int>(length);

            Assert.AreEqual(length, array.Length);
        }
Beispiel #3
0
        public void ChunkedArray_creates_appropriate_number_of_chunks()
        {
            int size       = 16 * 1024 * 4 + 100;
            int chunkCount = (int)Math.Ceiling((double)size * sizeof(int) / (16 * 1024));
            var array      = new ChunkedArray <int>(size);

            Assert.AreEqual(chunkCount, array.ChunkCount);
        }
Beispiel #4
0
 public void Can_get_expected_value_via_indexer()
 {
     var n = 16 * 1024 * 2 + 1800;
     var array = new ChunkedArray<int>(n);
     for(var i = 0; i < n; i++) {
         array[i] = 2 * i;
     }
     for(var i = 0; i < n; i++) {
         Assert.AreEqual(2 * i, array[i]);
     }
 }
Beispiel #5
0
 public void Can_enumerate_value_in_proper_order()
 {
     var n = 16 * 1024 * 2 + 1800;
     var array1 = new int[n];
     var array2 = new ChunkedArray<int>(n);
     for(var i = 0; i < n; i++) {
         array1[i] = i;
         array2[i] = i;
     }
     Assert.AreEqual(array1, array2.ToArray());
 }
Beispiel #6
0
        private static void MyersDiff <T>(T[] before, T[] after, Equality <T> equal, int maxdelta, IList <Tuple <ArrayDiffKind, T> > result) where T : class
        {
            // NOTE (steveb): we mark items as 'Added' when they are actually 'Removed' and vice versa; this means the initial 'before' and 'after' arrays must be passed in reversed order as well;
            //                the reason for doing so is that it will show first 'Removed' items, and then the 'Added' ones, which is what the 3-way merge algorithm requires.

            // initialize temp arrays required for search
            int max        = before.Length + after.Length + 1;
            var down_array = new ChunkedArray <int>(2 * max + 2);
            var up_array   = new ChunkedArray <int>(2 * max + 2);

            // run myers diff algorithm
            MyersDiffRev(after, 0, after.Length - 1, before, 0, before.Length - 1, equal, maxdelta, result, max, down_array, up_array);
        }
Beispiel #7
0
        public void Can_enumerate_value_in_proper_order()
        {
            var n      = 16 * 1024 * 2 + 1800;
            var array1 = new int[n];
            var array2 = new ChunkedArray <int>(n);

            for (var i = 0; i < n; i++)
            {
                array1[i] = i;
                array2[i] = i;
            }
            Assert.AreEqual(array1, array2.ToArray());
        }
Beispiel #8
0
        public void Can_get_expected_value_via_indexer()
        {
            var n     = 16 * 1024 * 2 + 1800;
            var array = new ChunkedArray <int>(n);

            for (var i = 0; i < n; i++)
            {
                array[i] = 2 * i;
            }
            for (var i = 0; i < n; i++)
            {
                Assert.AreEqual(2 * i, array[i]);
            }
        }
Beispiel #9
0
        private static void MyersDiffRev <T>(T[] before, int i_start, int i_end, T[] after, int j_start, int j_end, Equality <T> equal, int maxdelta, IList <Tuple <ArrayDiffKind, T> > result, int max, ChunkedArray <int> down_array, ChunkedArray <int> up_array) where T : class
        {
            // NOTE (steveb): we mark items as 'Added' when they are actually 'Removed' and vice versa; this means the initial 'before' and 'after' arrays must be passed in reversed order as well;
            //                the reason for doing so is that it will show first 'Removed' items, and then the 'Added' ones, which is what the 3-way merge algorithm requires.

            // skip matching items at the beginning
            while ((i_start <= i_end) && (j_start <= j_end) && equal(before[i_start], after[j_start]))
            {
                // add skipped item
                result.Add(new Tuple <ArrayDiffKind, T>(ArrayDiffKind.Same, before[i_start]));

                // move diagonally
                ++i_start;
                ++j_start;
            }

            // skip matching items at the end
            int tailCopyCount = 0;

            while ((i_start <= i_end) && (j_start <= j_end) && equal(before[i_end], after[j_end]))
            {
                // count skipped items
                ++tailCopyCount;

                // move diagonally
                --i_end;
                --j_end;
            }

            // check if we found a terminal case or if new need to recurse
            if (j_start > j_end)
            {
                // add remaining items as 'removed'
                while (i_start <= i_end)
                {
                    result.Add(new Tuple <ArrayDiffKind, T>(ArrayDiffKind.Added, before[i_start++]));
                }
            }
            else if (i_start > i_end)
            {
                // add remaining items as 'added'
                while (j_start <= j_end)
                {
                    result.Add(new Tuple <ArrayDiffKind, T>(ArrayDiffKind.Removed, after[j_start++]));
                }
            }
            else
            {
                // find the optimal path
                int i_split;
                int j_split;
                ComputeMyersSplit(before, i_start, i_end, out i_split, after, j_start, j_end, out j_split, equal, maxdelta, max, down_array, up_array);

                // solve sub-problem
                MyersDiffRev(before, i_start, i_split - 1, after, j_start, j_split - 1, equal, maxdelta, result, max, down_array, up_array);
                MyersDiffRev(before, i_split, i_end, after, j_split, j_end, equal, maxdelta, result, max, down_array, up_array);
            }

            // add tail items
            for (int k = 1; k <= tailCopyCount; ++k)
            {
                result.Add(new Tuple <ArrayDiffKind, T>(ArrayDiffKind.Same, before[i_end + k]));
            }
        }
Beispiel #10
0
        private static void ComputeMyersSplit <T>(T[] before, int i_start, int i_end, out int i_split, T[] after, int j_start, int j_end, out int j_split, Equality <T> equal, int maxdelta, int max, ChunkedArray <int> down_array, ChunkedArray <int> up_array)
        {
            // check if problem space is odd or even sized
            bool odd = (((i_end - i_start + 1) - (j_end - j_start + 1)) & 1) != 0;

            // the k-line to start the forward search
            int down_k = i_start - j_start;

            // the k-line to start the reverse search
            int up_k = i_end - j_end;

            // The vectors in the publication accepts negative indexes. the vectors implemented here are 0-based
            // and are access using a specific offset: UpOffset UpVector and DownOffset for DownVektor
            int down_offset = max - down_k;
            int up_offset   = max - up_k;

            // initialize arrays
            down_array[down_offset + down_k + 1] = i_start;
            up_array[up_offset + up_k - 1]       = i_end + 1;

            // find furthest reaching D-path
            int d_max = (((i_end - i_start + 1) + (j_end - j_start + 1) + 1) / 2);

            if (d_max >= maxdelta)
            {
                throw new ExceededDeltaException();
            }
            for (int d = 0; d <= d_max; ++d)
            {
                // search forward
                for (int k = down_k - d; k <= down_k + d; k += 2)
                {
                    // find the only or better starting point
                    int x;
                    int y;
                    if (k == down_k - d)
                    {
                        x = down_array[down_offset + k + 1]; // down
                    }
                    else
                    {
                        x = down_array[down_offset + k - 1] + 1; // a step to the right
                        if ((k < down_k + d) && (down_array[down_offset + k + 1] >= x))
                        {
                            x = down_array[down_offset + k + 1]; // down
                        }
                    }
                    y = x - k;

                    // find the end of the furthest reaching forward D-path in diagonal k
                    while ((x <= i_end) && (y <= j_end) && equal(before[x], after[y]))
                    {
                        ++x;
                        ++y;
                    }
                    down_array[down_offset + k] = x;

                    // overlap ?
                    if (odd && (up_k - d < k) && (k < up_k + d))
                    {
                        if (up_array[up_offset + k] <= down_array[down_offset + k])
                        {
                            i_split = down_array[down_offset + k];
                            j_split = down_array[down_offset + k] - k;
                            return;
                        }
                    }
                }

                // search backwards
                for (int k = up_k - d; k <= up_k + d; k += 2)
                {
                    // find the only or better starting point
                    int x;
                    int y;
                    if (k == up_k + d)
                    {
                        x = up_array[up_offset + k - 1]; // up
                    }
                    else
                    {
                        x = up_array[up_offset + k + 1] - 1; // left
                        if ((k > up_k - d) && (up_array[up_offset + k - 1] < x))
                        {
                            x = up_array[up_offset + k - 1]; // up
                        }
                    }
                    y = x - k;

                    while ((x > i_start) && (y > j_start) && equal(before[x - 1], after[y - 1]))
                    {
                        --x;
                        --y; // diagonal
                    }
                    up_array[up_offset + k] = x;

                    // overlap ?
                    if (!odd && (down_k - d <= k) && (k <= down_k + d))
                    {
                        if (up_array[up_offset + k] <= down_array[down_offset + k])
                        {
                            i_split = down_array[down_offset + k];
                            j_split = down_array[down_offset + k] - k;
                            return;
                        }
                    }
                }
            }
            throw new InvalidOperationException("this should never happen");
        }
Beispiel #11
0
 public void ChunkedArray_reports_proper_length()
 {
     var length = 16 * 1024 * 4 + 100;
     var array = new ChunkedArray<int>(length);
     Assert.AreEqual(length, array.Length);
 }
Beispiel #12
0
    void Update()
    {
        var ms = MusicManager.MusicState;

        while (_thoughts.Count < ThoughtCount)
        {
            var newThought = Instantiate(ThoughtPrefab.gameObject);
            newThought.transform.SetParent(transform);
            var newT = new Thought()
            {
                Transform = newThought.transform,
            };
            newT.Destination = newThought.transform.localPosition;
            _thoughts.Add(newT);
        }

        for (var i = 0; i < _thoughts.Count; ++i)
        {
            var t = _thoughts[i];
            if (Vector3.Distance(t.Destination, t.Transform.localPosition) < .1f)
            {
                Random.InitState(Time.frameCount + i);
                t.Destination = new Vector3(Random.Range(-CellRadius, CellRadius) * GridSize,
                                            Random.Range(-CellRadius, CellRadius) * GridSize,
                                            Random.Range(-CellRadius, CellRadius) * GridSize);
            }
            t.Transform.localPosition = Vector3.MoveTowards(t.Transform.localPosition, t.Destination, ThoughtSpeed * ms.Peak);
        }

        var cellDiameter = CellRadius * 2;
        var totalRadius  = (CellRadius * GridSize) / 2f;
        var arraySize    = (cellDiameter + 1) * (cellDiameter + 1) * (cellDiameter + 1);

        if (_matrices == null || _matrices.Count != arraySize)
        {
            _matrices = new ChunkedArray <Matrix4x4>(arraySize, 1023);
        }
        bool lastPhase = false;
        int  counter   = 0;

        for (var x = -CellRadius; x < CellRadius; ++x)
        {
            lastPhase = !lastPhase;
            for (var y = -CellRadius; y < CellRadius; ++y)
            {
                lastPhase = !lastPhase;
                for (var z = -CellRadius; z < CellRadius; ++z)
                {
                    var phase = GetPhase(lastPhase ? 1 : 0) * GridSize;
                    lastPhase = !lastPhase;
                    var pos = new Vector3(x, y, z) * GridSize + phase;

                    int magicInt = ((x + y) * z);
                    Random.InitState(magicInt);

                    var wl = Mathf.Lerp(ms.Wavelength[Random.Range(0, ms.Wavelength.Length - 1)] % 1, 1, ScaleMultiplier);
                    var s  = Scale.x + (Scale.y - Scale.x) * wl;

                    var mat = Matrix4x4.TRS(pos, Quaternion.identity, Vector3.one * s * GridSize);
                    mat = transform.localToWorldMatrix * mat;

                    _matrices[counter] = mat;
                    counter++;
                }
            }
        }
        foreach (Matrix4x4[] matrixArray in _matrices)
        {
            Graphics.DrawMeshInstanced(GridMesh, 0, GridMaterial, matrixArray, matrixArray.Length, null, ShadowCastingMode.Off, false, 0, null);
        }
    }