Short answer: it’s not CPU-dependent. What you’re seeing is a JIT bug in certain .NET/runtime versions, not a fundamental precision/accuracy issue with integer vectorization or division.
What’s going wrong
- Your alpha is a ushort (0x8000 = 32768). When it’s widened to 32-bit and then broadcast into a Vector128<int>/Vector128<uint>, the JIT sometimes sign-extends the 16-bit value instead of zero-extending it. So 0x8000 becomes 0xFFFF8000 (-32768) instead of 0x00008000 (32768).
- Once that “negative” value is used in element-wise integer arithmetic, you get overflows and off-by-one results like 32769 instead of 32768.
- This is why Vector128.Create((int)c.A) prints -32768, while Vector128.Create((int)32768) prints 32768, and Vector128.Create((int)c.A, …) also prints 32768. Different overloads/codegen paths avoid or trigger the buggy sign-extension.
Why you saw different behavior between environments
- Different sites/runtimes (SharpLab vs .NET Fiddle) were using different .NET/JIT builds. One had correct codegen, the other had the bug. That makes it look “platform/CPU-dependent,” but it’s actually version-dependent codegen.
Status
- You already filed the issue (dotnet/runtime#83387). This is the right place to track it. It’s a JIT codegen bug, not expected behavior.
Workarounds you can use now
- Force zero-extension explicitly before broadcasting/multiplying:
- Cast to uint (not int), or mask with 0xFFFF, and then Create the vector:
- var a = (uint)c.A;
- var aVec = Vector128.Create(a);
- v = v * aVec / Vector128.Create(65535u);
- Or for Vector<T>:
- var a = new Vector<uint>((uint)c.A);
- v = v * a / new Vector<uint>(65535u);
- Alternatively, use the multi-argument Create overload that you already observed behaves correctly:
- Vector128.Create((int)c.A, (int)c.A, (int)c.A, (int)c.A)
- Or ensure the cast is preserved as zero-extending:
- int a = c.A & 0xFFFF; // guarantees non-negative 32-bit
- var aVec = Vector128.Create((uint)a);
Takeaway
- The incorrect results aren’t due to integer division precision or CPU differences. They’re caused by a JIT sign-extension bug when widening ushort to 32-bit for certain Vector128.Create and operator code paths. Update to a runtime where it’s fixed, or apply the zero-extension workarounds above.