{"id":456,"date":"2021-06-20T12:18:47","date_gmt":"2021-06-20T12:18:47","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=456"},"modified":"2021-06-21T06:03:38","modified_gmt":"2021-06-21T06:03:38","slug":"jaggedarray-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2021\/06\/20\/jaggedarray-cs\/","title":{"rendered":"JaggedArray.cs"},"content":{"rendered":"\n<p>Jagged Array Collection Class (No Copy Resize)<\/p>\n\n\n\n<p>Updated: Jun-21,2021<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Collections;\nusing System.Collections.Generic;\nusing System.Diagnostics;\n\/\/\/ &lt;summary>\n\/\/\/     Uses a multidimensional array to create a growable array with out copy or re-allocation.\n\/\/\/ &lt;\/summary>\n[DebuggerDisplay(\"Count = {Count}\")]\n[Serializable]\npublic struct JaggedArray&lt;T> : IEnumerable&lt;T>, IDisposable\n{\n    private const int   FirstDimensionMax = 4096;\n    public const  int   ShiftCount        = 19;\n    public const  int   Granularity       = 1 &lt;&lt; ShiftCount;\n    private       bool  _disposed;\n    private       T[][] _array;\n    public        int   Count;\n    public        int   Length;\n    public        int   NumberOfActiveArrays;\n    public        bool  Allocated;\n    public JaggedArray(int size)\n    {\n        if (size &lt; Granularity)\n            size = Granularity;\n        try\n        {\n            NumberOfActiveArrays = (size + (Granularity - 1)) \/ Granularity;\n            Length               = NumberOfActiveArrays       * Granularity;\n            _array               = new T[FirstDimensionMax][];\n            for (var i = 0; i &lt; NumberOfActiveArrays; ++i)\n                _array[i] = new T[Granularity];\n        }\n        catch (Exception ex)\n        {\n            throw new Exception($\"Exception: {ex.Message}\");\n        }\n        Count     = 0;\n        _disposed = false;\n        Allocated = true;\n    }\n    public T this[int index]\n    {\n        get\n        {\n            if (index >= Length)\n                throw new Exception($\"Getter: Index out of bounds, Index: '{index}' must be less than the Length: '{Length}'.\");\n            return _array[index >> ShiftCount][index &amp; (Granularity - 1)];\n        }\n        set\n        {\n            if (index >= Length)\n                ResizeArray();\n            _array[index >> ShiftCount][index &amp; (Granularity - 1)] = value;\n            Count++;\n        }\n    }\n    public void Dispose()\n    {\n        Dispose(true);\n    }\n    IEnumerator&lt;T> IEnumerable&lt;T>.GetEnumerator()\n    {\n        return GetEnumerator();\n    }\n    IEnumerator IEnumerable.GetEnumerator()\n    {\n        return GetEnumerator();\n    }\n    public void Add(T Item)\n    {\n        if (Count >= Length)\n            ResizeArray();\n        var x = Count >> ShiftCount;\n        var y = Count &amp; (Granularity - 1);\n        _array[x][y] = Item;\n        Count++;\n    }\n    private void ResizeArray()\n    {\n        try\n        {\n            _array[NumberOfActiveArrays] = new T[Granularity];\n            NumberOfActiveArrays++;\n        }\n        catch (Exception ex)\n        {\n            throw new Exception($\"Exception: {ex.Message}\");\n        }\n    }\n    public void Zero()\n    {\n        for (var a = 0L; a &lt; NumberOfActiveArrays; a++)\n            _array[a] = Array.Empty&lt;T>();\n        Count = 0;\n    }\n    public void Clear()\n    {\n        for (var a = 0L; a &lt; NumberOfActiveArrays; a++)\n            Array.Clear(_array[a], 0, Granularity);\n        Count = 0;\n    }\n    public int IndexOf(T item)\n    {\n        var i = 0;\n        for (; i &lt; NumberOfActiveArrays; i++)\n        {\n            var pos = Array.IndexOf(_array[i], item, 0);\n            if (pos != -1)\n                return i * Granularity + pos;\n        }\n        return -1;\n    }\n    public JaggedArray&lt;T> Copy(int newsize)\n    {\n        var temp = new JaggedArray&lt;T>(newsize);\n        for (var a = 0L; a &lt; NumberOfActiveArrays; a++)\n            Array.Copy(_array[a], temp._array[a], Granularity);\n        temp.Count = Count;\n        return temp;\n    }\n    public void FromArray(T[][] array)\n    {\n        NumberOfActiveArrays = array.GetUpperBound(0) + 1;\n        Length               = NumberOfActiveArrays * Granularity;\n        _array               = new T[NumberOfActiveArrays][];\n        for (var i = 0; i &lt; NumberOfActiveArrays; ++i)\n            _array[i] = new T[Granularity];\n        for (var a = 0L; a &lt; NumberOfActiveArrays; a++)\n            Array.Copy(array[a], _array[a], Granularity);\n    }\n    public T[][] ToRawArray()\n    {\n        var ta = new T[NumberOfActiveArrays][];\n        for (var i = 0; i &lt; NumberOfActiveArrays; ++i)\n            ta[i] = new T[Granularity];\n        for (var a = 0L; a &lt; NumberOfActiveArrays; a++)\n            Array.Copy(_array[a], ta[a], Granularity);\n        return ta;\n    }\n    public T[] ToArray()\n    {\n        var newArray = new T[Count];\n        using (var en = GetEnumerator())\n        {\n            var ptr = 0;\n            while (en.MoveNext())\n            {\n                var value = en.Current;\n                if (value == null)\n                    break;\n                newArray[ptr++] = value;\n            }\n            return newArray;\n        }\n    }\n    private void Dispose(bool disposing)\n    {\n        if (!_disposed)\n            if (disposing)\n                _array = null;\n        _disposed = true;\n    }\n    public IEnumerator&lt;T> GetEnumerator()\n    {\n        return GetEnum();\n    }\n    public IEnumerator&lt;T> GetEnum()\n    {\n        for (var i = 0; i &lt; Count; i++)\n            yield return this[i];\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Jagged Array Collection Class (No Copy Resize) Updated: Jun-21,2021<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[188,189,190],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/456"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=456"}],"version-history":[{"count":2,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/456\/revisions"}],"predecessor-version":[{"id":465,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/456\/revisions\/465"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=456"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=456"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=456"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}