Skip to content

Commit 18f7acc

Browse files
authored
Introduce VBuffer GetValues and GetIndices (#1536)
* Introduce VBuffer GetValues and GetIndices Use the new methods in place of Count and Values/Indices in as many readonly situations as possible. Working towards #608 Update the rest of the BinaryWriter utils to use Span.
1 parent d3b70b5 commit 18f7acc

File tree

59 files changed

+596
-692
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+596
-692
lines changed

src/Microsoft.ML.Core/Data/VBuffer.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ public readonly struct VBuffer<T>
3838
/// </summary>
3939
public readonly int[] Indices;
4040

41+
/// <summary>
42+
/// The explicitly represented values.
43+
/// </summary>
44+
public ReadOnlySpan<T> GetValues() => Values.AsSpan(0, Count);
45+
46+
/// <summary>
47+
/// The indices. For a dense representation, this array is not used. For a sparse representation
48+
/// it is parallel to values and specifies the logical indices for the corresponding values.
49+
/// </summary>
50+
/// <remarks>
51+
/// For example, if GetIndices() returns [3, 5] and GetValues() produces [98, 76], this VBuffer
52+
/// stands for a vector with:
53+
/// - non-zeros values 98 and 76 respectively at the 4th and 6th coordinates
54+
/// - zeros at all other coordinates
55+
/// </remarks>
56+
public ReadOnlySpan<int> GetIndices() => IsDense ? default : Indices.AsSpan(0, Count);
57+
4158
/// <summary>
4259
/// Equivalent to Count == Length.
4360
/// </summary>

src/Microsoft.ML.Core/Utilities/BigArray.cs

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -306,46 +306,45 @@ public void TrimCapacity()
306306
}
307307

308308
/// <summary>
309-
/// Appends the first <paramref name="length"/> elements of <paramref name="src"/> to the end.
309+
/// Appends the elements of <paramref name="src"/> to the end.
310310
/// This method is thread safe related to calls to <see cref="M:CopyTo"/> (assuming those copy operations
311311
/// are happening over ranges already added), but concurrent calls to
312312
/// <see cref="M:AddRange"/> should not be attempted. Intended usage is that
313313
/// one thread will call this method, while multiple threads may access
314314
/// previously added ranges from <see cref="M:CopyTo"/>, concurrently with
315315
/// this method or themselves.
316316
/// </summary>
317-
public void AddRange(T[] src, int length)
317+
public void AddRange(ReadOnlySpan<T> src)
318318
{
319-
Contracts.Assert(0 <= length && length <= Utils.Size(src));
320-
if (length == 0)
319+
if (src.IsEmpty)
321320
return;
322-
Contracts.AssertValue(src);
323321

324322
int maMin;
325323
int miMin;
326324
int maMax;
327325
int miLim;
328326
LongMinToMajorMinorMin(_length, out maMin, out miMin);
329-
LongLimToMajorMaxMinorLim(_length + length, out maMax, out miLim);
327+
LongLimToMajorMaxMinorLim(_length + src.Length, out maMax, out miLim);
330328

331329
Contracts.Assert(maMin <= maMax); // Could be violated if length == 0, but we already took care of this.
332330
Utils.EnsureSize(ref _entries, maMax + 1, BlockSize);
333331
switch (maMax - maMin)
334332
{
335333
case 0:
336334
// Spans only one subarray, most common case and simplest implementation.
337-
Contracts.Assert(miLim - miMin == length);
335+
Contracts.Assert(miLim - miMin == src.Length);
338336
Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
339-
Array.Copy(src, 0, _entries[maMax], miMin, length);
337+
src.CopyTo(_entries[maMax].AsSpan(miMin));
340338
break;
341339
case 1:
342340
// Spans two subarrays.
343-
Contracts.Assert((BlockSize - miMin) + miLim == length);
341+
Contracts.Assert((BlockSize - miMin) + miLim == src.Length);
344342
Utils.EnsureSize(ref _entries[maMin], BlockSize, BlockSize);
345-
Array.Copy(src, 0, _entries[maMin], miMin, BlockSize - miMin);
343+
int firstSubArrayCapacity = BlockSize - miMin;
344+
src.Slice(0, firstSubArrayCapacity).CopyTo(_entries[maMin].AsSpan(miMin));
346345
Contracts.Assert(_entries[maMax] == null);
347346
Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
348-
Array.Copy(src, BlockSize - miMin, _entries[maMax], 0, miLim);
347+
src.Slice(firstSubArrayCapacity, miLim).CopyTo(_entries[maMax]);
349348
break;
350349
default:
351350
// Spans three or more subarrays. Very rare.
@@ -354,24 +353,24 @@ public void AddRange(T[] src, int length)
354353
// Copy the first segment.
355354
Utils.EnsureSize(ref _entries[maMin], BlockSize, BlockSize);
356355
int srcSoFar = BlockSize - miMin;
357-
Array.Copy(src, 0, _entries[maMin], miMin, srcSoFar);
356+
src.Slice(0, srcSoFar).CopyTo(_entries[maMin].AsSpan(miMin));
358357
// Copy the internal segments.
359358
for (int major = maMin + 1; major < maMax; ++major)
360359
{
361360
Contracts.Assert(_entries[major] == null);
362361
_entries[major] = new T[BlockSize];
363-
Array.Copy(src, srcSoFar, _entries[major], 0, BlockSize);
362+
src.Slice(srcSoFar, BlockSize).CopyTo(_entries[major]);
364363
srcSoFar += BlockSize;
365-
Contracts.Assert(srcSoFar < length);
364+
Contracts.Assert(srcSoFar < src.Length);
366365
}
367366
// Copy the last segment.
368-
Contracts.Assert(length - srcSoFar == miLim);
367+
Contracts.Assert(src.Length - srcSoFar == miLim);
369368
Contracts.Assert(_entries[maMax] == null);
370369
Utils.EnsureSize(ref _entries[maMax], maMax >= FullAllocationBeyond ? BlockSize : miLim, BlockSize);
371-
Array.Copy(src, srcSoFar, _entries[maMax], 0, miLim);
370+
src.Slice(srcSoFar, miLim).CopyTo(_entries[maMax]);
372371
break;
373372
}
374-
_length += length;
373+
_length += src.Length;
375374
}
376375

377376
/// <summary>

0 commit comments

Comments
 (0)