Skip to content

Commit 5497eb8

Browse files
committed
Added internal RefEnumerableHelper type
1 parent 60e17b4 commit 5497eb8

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Runtime.CompilerServices;
6+
7+
namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals
8+
{
9+
/// <summary>
10+
/// Helpers to process sequences of values by reference with a given step.
11+
/// </summary>
12+
internal static class RefEnumerableHelper
13+
{
14+
/// <summary>
15+
/// Clears a target memory area.
16+
/// </summary>
17+
/// <typeparam name="T">The type of values to clear.</typeparam>
18+
/// <param name="r0">A <typeparamref name="T"/> reference to the start of the memory area.</param>
19+
/// <param name="length">The number of items in the memory area.</param>
20+
/// <param name="step">The number of items between each consecutive target value.</param>
21+
public static void Clear<T>(ref T r0, nint length, nint step)
22+
{
23+
nint offset = 0;
24+
25+
// Main loop with 8 unrolled iterations
26+
while (length >= 8)
27+
{
28+
Unsafe.Add(ref r0, offset) = default!;
29+
Unsafe.Add(ref r0, offset += step) = default!;
30+
Unsafe.Add(ref r0, offset += step) = default!;
31+
Unsafe.Add(ref r0, offset += step) = default!;
32+
Unsafe.Add(ref r0, offset += step) = default!;
33+
Unsafe.Add(ref r0, offset += step) = default!;
34+
Unsafe.Add(ref r0, offset += step) = default!;
35+
Unsafe.Add(ref r0, offset += step) = default!;
36+
37+
length -= 8;
38+
offset += step;
39+
}
40+
41+
if (length >= 4)
42+
{
43+
Unsafe.Add(ref r0, offset) = default!;
44+
Unsafe.Add(ref r0, offset += step) = default!;
45+
Unsafe.Add(ref r0, offset += step) = default!;
46+
Unsafe.Add(ref r0, offset += step) = default!;
47+
48+
length -= 4;
49+
offset += step;
50+
}
51+
52+
// Clear the remaining values
53+
while (length > 0)
54+
{
55+
Unsafe.Add(ref r0, offset) = default!;
56+
57+
length -= 1;
58+
offset += step;
59+
}
60+
}
61+
62+
/// <summary>
63+
/// Copies a sequence of discontiguous items from one memory area to another.
64+
/// </summary>
65+
/// <typeparam name="T">The type of items to copy.</typeparam>
66+
/// <param name="sourceRef">The source reference to copy from.</param>
67+
/// <param name="destinationRef">The target reference to copy to.</param>
68+
/// <param name="length">The total number of items to copy.</param>
69+
/// <param name="step">The step between consecutive items in the memory area pointed to by <paramref name="sourceRef"/>.</param>
70+
public static void CopyTo<T>(ref T sourceRef, ref T destinationRef, nint length, nint step)
71+
{
72+
nint
73+
sourceOffset = 0,
74+
destinationOffset = 0;
75+
76+
while (length >= 8)
77+
{
78+
Unsafe.Add(ref destinationRef, destinationOffset + 0) = Unsafe.Add(ref sourceRef, sourceOffset);
79+
Unsafe.Add(ref destinationRef, destinationOffset + 1) = Unsafe.Add(ref sourceRef, sourceOffset += step);
80+
Unsafe.Add(ref destinationRef, destinationOffset + 2) = Unsafe.Add(ref sourceRef, sourceOffset += step);
81+
Unsafe.Add(ref destinationRef, destinationOffset + 3) = Unsafe.Add(ref sourceRef, sourceOffset += step);
82+
Unsafe.Add(ref destinationRef, destinationOffset + 4) = Unsafe.Add(ref sourceRef, sourceOffset += step);
83+
Unsafe.Add(ref destinationRef, destinationOffset + 5) = Unsafe.Add(ref sourceRef, sourceOffset += step);
84+
Unsafe.Add(ref destinationRef, destinationOffset + 6) = Unsafe.Add(ref sourceRef, sourceOffset += step);
85+
Unsafe.Add(ref destinationRef, destinationOffset + 7) = Unsafe.Add(ref sourceRef, sourceOffset += step);
86+
87+
length -= 8;
88+
sourceOffset += step;
89+
destinationOffset += 8;
90+
}
91+
92+
if (length >= 4)
93+
{
94+
Unsafe.Add(ref destinationRef, destinationOffset + 0) = Unsafe.Add(ref sourceRef, sourceOffset);
95+
Unsafe.Add(ref destinationRef, destinationOffset + 1) = Unsafe.Add(ref sourceRef, sourceOffset += step);
96+
Unsafe.Add(ref destinationRef, destinationOffset + 2) = Unsafe.Add(ref sourceRef, sourceOffset += step);
97+
Unsafe.Add(ref destinationRef, destinationOffset + 3) = Unsafe.Add(ref sourceRef, sourceOffset += step);
98+
99+
length -= 4;
100+
sourceOffset += step;
101+
destinationOffset += 4;
102+
}
103+
104+
while (length > 0)
105+
{
106+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
107+
108+
length -= 1;
109+
sourceOffset += step;
110+
destinationOffset += 1;
111+
}
112+
}
113+
114+
/// <summary>
115+
/// 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.
117+
/// </summary>
118+
/// <typeparam name="T">The type of items to copy.</typeparam>
119+
/// <param name="sourceRef">The source reference to copy from.</param>
120+
/// <param name="destinationRef">The target reference to copy to.</param>
121+
/// <param name="length">The total number of items to copy.</param>
122+
/// <param name="step">The step between consecutive items in the memory area pointed to by <paramref name="sourceRef"/>.</param>
123+
public static void CopyFrom<T>(ref T sourceRef, ref T destinationRef, nint length, nint step)
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 += step) = Unsafe.Add(ref sourceRef, sourceOffset + 1);
133+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 2);
134+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 3);
135+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 4);
136+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 5);
137+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 6);
138+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 7);
139+
140+
length -= 8;
141+
sourceOffset += 8;
142+
destinationOffset += step;
143+
}
144+
145+
if (length >= 4)
146+
{
147+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
148+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 1);
149+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 2);
150+
Unsafe.Add(ref destinationRef, destinationOffset += step) = Unsafe.Add(ref sourceRef, sourceOffset + 3);
151+
152+
length -= 4;
153+
sourceOffset += 4;
154+
destinationOffset += step;
155+
}
156+
157+
while (length > 0)
158+
{
159+
Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset);
160+
161+
length -= 1;
162+
sourceOffset += 1;
163+
destinationOffset += step;
164+
}
165+
}
166+
167+
/// <summary>
168+
/// Fills a target memory area.
169+
/// </summary>
170+
/// <typeparam name="T">The type of values to fill.</typeparam>
171+
/// <param name="r0">A <typeparamref name="T"/> reference to the start of the memory area.</param>
172+
/// <param name="length">The number of items in the memory area.</param>
173+
/// <param name="step">The number of items between each consecutive target value.</param>
174+
/// <param name="value">The value to assign to every item in the target memory area.</param>
175+
public static void Fill<T>(ref T r0, nint length, nint step, T value)
176+
{
177+
nint offset = 0;
178+
179+
while (length >= 8)
180+
{
181+
Unsafe.Add(ref r0, offset) = value;
182+
Unsafe.Add(ref r0, offset += step) = value;
183+
Unsafe.Add(ref r0, offset += step) = value;
184+
Unsafe.Add(ref r0, offset += step) = value;
185+
Unsafe.Add(ref r0, offset += step) = value;
186+
Unsafe.Add(ref r0, offset += step) = value;
187+
Unsafe.Add(ref r0, offset += step) = value;
188+
Unsafe.Add(ref r0, offset += step) = value;
189+
190+
length -= 8;
191+
offset += step;
192+
}
193+
194+
if (length >= 4)
195+
{
196+
Unsafe.Add(ref r0, offset) = value;
197+
Unsafe.Add(ref r0, offset += step) = value;
198+
Unsafe.Add(ref r0, offset += step) = value;
199+
Unsafe.Add(ref r0, offset += step) = value;
200+
201+
length -= 4;
202+
offset += step;
203+
}
204+
205+
while (length > 0)
206+
{
207+
Unsafe.Add(ref r0, offset) = value;
208+
209+
length -= 1;
210+
offset += step;
211+
}
212+
}
213+
}
214+
}

0 commit comments

Comments
 (0)