예제 #1
0
        /// <summary>
        /// Adds the value as a TItem. Does not check whether the TItem is already present.
        /// Returns the index of the added value.
        /// </summary>
        private int AddCore(TItem val, int iit)
        {
            AssertValid();
            Contracts.Assert(val != null);
            Contracts.Assert(0 <= iit && iit < _rgit.Length);

            if (_ct >= Utils.Size(_entries))
            {
                Contracts.Assert(_ct == Utils.Size(_entries));
                Utils.EnsureSize(ref _entries, _ct + 1);
            }
            Contracts.Assert(_ct < _entries.Length);

            _entries[_ct].Value  = val;
            _entries[_ct].ItNext = _rgit[iit];
            _rgit[iit]           = _ct;

            if (++_ct >= _rgit.Length)
            {
                GrowTable();
            }

            AssertValid();

            // Return the index of the added value.
            return(_ct - 1);
        }
        public static void ToArray <T>(this Tensor tensor, ref T[] array) where T : unmanaged
        {
            Utils.EnsureSize(ref array, (int)tensor.size, (int)tensor.size, false);
            var span = new Span <T>(array);

            CopyTo(tensor, span);
        }
예제 #3
0
        /// <summary>
        /// Appends the elements of <paramref name="src"/> to the end.
        /// This method is thread safe related to calls to <see cref="M:CopyTo"/> (assuming those copy operations
        /// are happening over ranges already added), but concurrent calls to
        /// <see cref="M:AddRange"/> should not be attempted. Intended usage is that
        /// one thread will call this method, while multiple threads may access
        /// previously added ranges from <see cref="M:CopyTo"/>, concurrently with
        /// this method or themselves.
        /// </summary>
        public void AddRange(ReadOnlySpan <T> src)
        {
            if (src.IsEmpty)
            {
                return;
            }

            int maMin;
            int miMin;
            int maMax;
            int miLim;

            LongMinToMajorMinorMin(_length, out maMin, out miMin);
            LongLimToMajorMaxMinorLim(_length + src.Length, out maMax, out miLim);

            Contracts.Assert(maMin <= maMax); // Could be violated if length == 0, but we already took care of this.
            Utils.EnsureSize(ref _entries, maMax + 1, BlockSize);
            switch (maMax - maMin)
            {
            case 0:
                // Spans only one subarray, most common case and simplest implementation.
                Contracts.Assert(miLim - miMin == src.Length);
                Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
                src.CopyTo(_entries[maMax].AsSpan(miMin));
                break;

            case 1:
                // Spans two subarrays.
                Contracts.Assert((BlockSize - miMin) + miLim == src.Length);
                Utils.EnsureSize(ref _entries[maMin], BlockSize, BlockSize);
                int firstSubArrayCapacity = BlockSize - miMin;
                src.Slice(0, firstSubArrayCapacity).CopyTo(_entries[maMin].AsSpan(miMin));
                Contracts.Assert(_entries[maMax] == null);
                Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
                src.Slice(firstSubArrayCapacity, miLim).CopyTo(_entries[maMax]);
                break;

            default:
                // Spans three or more subarrays. Very rare.
                int miSubMin = miMin;

                // Copy the first segment.
                Utils.EnsureSize(ref _entries[maMin], BlockSize, BlockSize);
                int srcSoFar = BlockSize - miMin;
                src.Slice(0, srcSoFar).CopyTo(_entries[maMin].AsSpan(miMin));
                // Copy the internal segments.
                for (int major = maMin + 1; major < maMax; ++major)
                {
                    Contracts.Assert(_entries[major] == null);
                    _entries[major] = new T[BlockSize];
                    src.Slice(srcSoFar, BlockSize).CopyTo(_entries[major]);
                    srcSoFar += BlockSize;
                    Contracts.Assert(srcSoFar < src.Length);
                }
                // Copy the last segment.
                Contracts.Assert(src.Length - srcSoFar == miLim);
                Contracts.Assert(_entries[maMax] == null);
                Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
                src.Slice(srcSoFar, miLim).CopyTo(_entries[maMax]);
                break;
            }
            _length += src.Length;
        }