|
5 | 5 | using System.Runtime.CompilerServices;
|
6 | 6 | using System.Runtime.InteropServices;
|
7 | 7 | using System.Runtime.Intrinsics;
|
| 8 | +using System.Runtime.Intrinsics.Arm; |
8 | 9 | using System.Runtime.Intrinsics.X86;
|
9 | 10 | using SixLabors.ImageSharp.Memory;
|
10 | 11 |
|
@@ -122,12 +123,26 @@ static void SumVertical(Span<float> target, Span<float> source)
|
122 | 123 | ref Vector256<float> sourceVectorRef = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(source));
|
123 | 124 |
|
124 | 125 | // Spans are guaranteed to be multiple of 8 so no extra 'remainder' steps are needed
|
| 126 | + DebugGuard.IsTrue(source.Length % 8 == 0, "source must be multiple of 8"); |
125 | 127 | nuint count = source.Vector256Count<float>();
|
126 | 128 | for (nuint i = 0; i < count; i++)
|
127 | 129 | {
|
128 | 130 | Unsafe.Add(ref targetVectorRef, i) = Avx.Add(Unsafe.Add(ref targetVectorRef, i), Unsafe.Add(ref sourceVectorRef, i));
|
129 | 131 | }
|
130 | 132 | }
|
| 133 | + else if (AdvSimd.IsSupported) |
| 134 | + { |
| 135 | + ref Vector128<float> targetVectorRef = ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(target)); |
| 136 | + ref Vector128<float> sourceVectorRef = ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(source)); |
| 137 | + |
| 138 | + // Spans are guaranteed to be multiple of 8 so no extra 'remainder' steps are needed |
| 139 | + DebugGuard.IsTrue(source.Length % 8 == 0, "source must be multiple of 8"); |
| 140 | + nuint count = source.Vector128Count<float>(); |
| 141 | + for (nuint i = 0; i < count; i++) |
| 142 | + { |
| 143 | + Unsafe.Add(ref targetVectorRef, i) = AdvSimd.Add(Unsafe.Add(ref targetVectorRef, i), Unsafe.Add(ref sourceVectorRef, i)); |
| 144 | + } |
| 145 | + } |
131 | 146 | else
|
132 | 147 | {
|
133 | 148 | ref Vector<float> targetVectorRef = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(target));
|
@@ -200,13 +215,27 @@ static void MultiplyToAverage(Span<float> target, float multiplier)
|
200 | 215 | ref Vector256<float> targetVectorRef = ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(target));
|
201 | 216 |
|
202 | 217 | // Spans are guaranteed to be multiple of 8 so no extra 'remainder' steps are needed
|
| 218 | + DebugGuard.IsTrue(target.Length % 8 == 0, "target must be multiple of 8"); |
203 | 219 | nuint count = target.Vector256Count<float>();
|
204 |
| - var multiplierVector = Vector256.Create(multiplier); |
| 220 | + Vector256<float> multiplierVector = Vector256.Create(multiplier); |
205 | 221 | for (nuint i = 0; i < count; i++)
|
206 | 222 | {
|
207 | 223 | Unsafe.Add(ref targetVectorRef, i) = Avx.Multiply(Unsafe.Add(ref targetVectorRef, i), multiplierVector);
|
208 | 224 | }
|
209 | 225 | }
|
| 226 | + else if (AdvSimd.IsSupported) |
| 227 | + { |
| 228 | + ref Vector128<float> targetVectorRef = ref Unsafe.As<float, Vector128<float>>(ref MemoryMarshal.GetReference(target)); |
| 229 | + |
| 230 | + // Spans are guaranteed to be multiple of 8 so no extra 'remainder' steps are needed |
| 231 | + DebugGuard.IsTrue(target.Length % 8 == 0, "target must be multiple of 8"); |
| 232 | + nuint count = target.Vector128Count<float>(); |
| 233 | + Vector128<float> multiplierVector = Vector128.Create(multiplier); |
| 234 | + for (nuint i = 0; i < count; i++) |
| 235 | + { |
| 236 | + Unsafe.Add(ref targetVectorRef, i) = AdvSimd.Multiply(Unsafe.Add(ref targetVectorRef, i), multiplierVector); |
| 237 | + } |
| 238 | + } |
210 | 239 | else
|
211 | 240 | {
|
212 | 241 | ref Vector<float> targetVectorRef = ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(target));
|
|
0 commit comments