< Summary

Class:GDX.Collections.Generic.CoalesceArray[T]
Assembly:GDX
File(s):./Packages/com.dotbunny.gdx/GDX/Collections/Generic/CoalesceArray.cs
Covered lines:0
Uncovered lines:77
Coverable lines:77
Total lines:156
Line coverage:0% (0 of 77)
Covered branches:0
Total branches:0
Covered methods:0
Total methods:8
Method coverage:0% (0 of 8)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
CoalesceArray(...)0%42600%
GetBucket(...)0%2100%
GetBucketCount()0%2100%
GetBucketLocation(...)0%2100%
Resize(...)0%42600%

File(s)

./Packages/com.dotbunny.gdx/GDX/Collections/Generic/CoalesceArray.cs

#LineLine coverage
 1// Copyright (c) 2020-2023 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System.Runtime.CompilerServices;
 6using Unity.Collections.LowLevel.Unsafe;
 7using Unity.Mathematics;
 8
 9namespace GDX.Collections.Generic
 10{
 11    /// <summary>
 12    ///     Multiple arrays acting as one uniform coalesced array.
 13    /// </summary>
 14    /// <remarks>Stores a maximum of 18,446,744,073,709,551,615 elements.</remarks>
 15    /// <typeparam name="T">The type of data to be stored.</typeparam>
 16    public struct CoalesceArray<T>
 17    {
 18        const ulong k_MaxByteSize = 2147483648;
 19        /// <summary>
 20        ///     The internal arrays storage
 21        /// </summary>
 22        SimpleList<T[]> m_Buckets;
 23
 24        /// <summary>
 25        ///     The block size used to allocate new arrays.
 26        /// </summary>
 27        readonly ulong m_BucketSize;
 28
 29        /// <summary>
 30        ///     Cached version of the bucket size, minus one used in <see cref="GetBucketLocation"/>.
 31        /// </summary>
 32        readonly ulong m_BucketSizeMinusOne;
 33
 34        /// <summary>
 35        ///     The number of elements the <see cref="CoalesceArray{T}"/> is capable of holding.
 36        /// </summary>
 37        ulong m_Length;
 38
 39        public CoalesceArray(ulong length)
 040        {
 041            int sizeOf = UnsafeUtility.SizeOf(typeof(T));
 042            ulong expectedSize = length * (ulong)sizeOf;
 43
 44            // Check if we've wrapped around, if the size is bigger then our max data size, or if the length will exceed
 45            // the array address space.
 046            if (expectedSize < length || expectedSize > k_MaxByteSize || length >= k_MaxByteSize)
 047            {
 048                m_BucketSize = k_MaxByteSize / (ulong)sizeOf;
 049            }
 50            else
 051            {
 052                m_BucketSize = math.ceilpow2(length);
 053            }
 054            m_BucketSizeMinusOne = m_BucketSize - 1;
 55
 56            // Build our empty arrays
 057            ulong remainder = length & m_BucketSizeMinusOne;
 058            int extraArray = 0;
 059            if (remainder > 0)
 060            {
 061                extraArray = 1;
 062            }
 063            int placesToShift = math.tzcnt(m_BucketSize);
 064            int arrayCount = (int)(length >> placesToShift) + extraArray;
 065            m_Buckets = new SimpleList<T[]>(arrayCount);
 066            for (int i = 0; i < arrayCount; i++)
 067            {
 068                m_Buckets.Array[i] = new T[(int)m_BucketSize];
 069            }
 70
 071            m_Length = length;
 072        }
 73
 74        public T this[ulong index]
 75        {
 76            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 77            get
 078            {
 079                (int bucketIndex, int bucketOffset) info = GetBucketLocation(index);
 080                return m_Buckets.Array[info.bucketIndex][info.bucketOffset];
 081            }
 82
 83            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 84            set
 085            {
 086                (int bucketIndex, int bucketOffset) info = GetBucketLocation(index);
 087                m_Buckets.Array[info.bucketIndex][info.bucketOffset] = value;
 088            }
 89        }
 90
 91        public ulong Length
 92        {
 093            get => m_Length;
 94        }
 95
 96        public ref T[] GetBucket(int bucketIndex)
 097        {
 098            return ref m_Buckets.Array[bucketIndex];
 099        }
 100
 101        public int GetBucketCount()
 0102        {
 0103            return m_Buckets.Count;
 0104        }
 105
 106        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 107        public (int bucketIndex, int bucketOffset) GetBucketLocation(ulong index)
 0108        {
 0109            int bucketOffset = (int)(index & m_BucketSizeMinusOne);
 0110            int placesToShift = math.tzcnt(m_BucketSize);
 0111            int bucketIndex = (int)(index >> placesToShift);
 0112            return (bucketIndex, bucketOffset);
 0113        }
 114
 115        public bool Resize(ulong desiredLength)
 0116        {
 0117            ulong remainder = desiredLength & m_BucketSizeMinusOne;
 0118            int extraArray = 0;
 0119            if (remainder > 0)
 0120            {
 0121                extraArray = 1;
 0122            }
 0123            int arrayCount = (int)((desiredLength - remainder) / m_BucketSize) + extraArray;
 0124            int previousCount = m_Buckets.Count;
 125
 126            // Grow
 0127            if (arrayCount > previousCount)
 0128            {
 0129                int additionalCount = arrayCount - previousCount;
 0130                for (int i = 0; i < additionalCount; i++)
 0131                {
 0132                    m_Buckets.AddWithExpandCheck(new T[m_BucketSize]);
 0133                }
 0134                m_Length = desiredLength;
 0135                return true;
 136            }
 137
 138            // Shrink
 0139            if (arrayCount < previousCount)
 0140            {
 0141                int extraCount = previousCount - arrayCount;
 0142                for (int i = 0; i < extraCount; i++)
 0143                {
 0144                    m_Buckets.RemoveFromBack();
 0145                }
 0146                m_Length = desiredLength;
 0147                return true;
 148            }
 149
 150            // Do nothing
 0151            m_Length = desiredLength;
 0152            return false;
 0153        }
 154
 155    }
 156}