Skip to content

Commit 7ab524d

Browse files
committed
Added RefEnumerableHelper.CopyTo 2-step overload
1 parent e54a545 commit 7ab524d

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

Microsoft.Toolkit.HighPerformance/Helpers/Internals/RefEnumerableHelper.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,62 @@ public static void CopyTo<T>(ref T sourceRef, ref T destinationRef, nint length,
111111
}
112112
}
113113

114+
/// <summary>
115+
/// Copies a sequence of discontiguous items from one memory area to another.
116+
/// </summary>
117+
/// <typeparam name="T">The type of items to copy.</typeparam>
118+
/// <param name="sourceRef">The source reference to copy from.</param>
119+
/// <param name="destinationRef">The target reference to copy to.</param>
120+
/// <param name="length">The total number of items to copy.</param>
121+
/// <param name="sourceStep">The step between consecutive items in the memory area pointed to by <paramref name="sourceRef"/>.</param>
122+
/// <param name="destinationStep">The step between consecutive items in the memory area pointed to by <paramref name="destinationRef"/>.</param>
123+
public static void CopyTo<T>(ref T sourceRef, ref T destinationRef, nint length, nint sourceStep, nint destinationStep)
124+
{
125+
nint
126+
sourceOffset = 0,
127+
destinationOffset = 0;
128+
129+
while (length >= 8)
130+
{
131+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
132+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
133+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
134+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
135+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
136+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
137+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
138+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
139+
140+
length -= 8;
141+
sourceOffset += sourceStep;
142+
destinationOffset += destinationStep;
143+
}
144+
145+
if (length >= 4)
146+
{
147+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
148+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
149+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
150+
Unsafe.Add(ref destinationRef, destinationOffset += destinationStep) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep);
151+
152+
length -= 4;
153+
sourceOffset += sourceStep;
154+
destinationOffset += destinationStep;
155+
}
156+
157+
while (length > 0)
158+
{
159+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
160+
161+
length -= 1;
162+
sourceOffset += sourceStep;
163+
destinationOffset += destinationStep;
164+
}
165+
}
166+
114167
/// <summary>
115168
/// Copies a sequence of discontiguous items from one memory area to another. This mirrors
116-
/// <see cref="CopyTo"/>, but <paramref name="step"/> refers to <paramref name="destinationRef"/> instead.
169+
/// <see cref="CopyTo{T}(ref T,ref T,nint,nint)"/>, but <paramref name="step"/> refers to <paramref name="destinationRef"/> instead.
117170
/// </summary>
118171
/// <typeparam name="T">The type of items to copy.</typeparam>
119172
/// <param name="sourceRef">The source reference to copy from.</param>

0 commit comments

Comments
 (0)