/// <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); }
/// <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; }