|
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