Description
Description
In case of an overflow for multiplication *
and remainder %
System.Int128
gives wrong results.
All other C# integer types behave in this case correctly like standard on all machines and platforms.
The problem is that there are many algorithms that assume correct partial results in case of an overflow as part of the calculation.
All these algorithms can fail with Int128 and it's dangerous because the user wouldn't expect it.
The bug is in public static Int128 operator *(Int128 left, Int128 right)
Easy to see that the case is simply not handled and the final return new Int128(result.Upper | sign, result.Lower);
copys the sign always.
This is like a proof as the sign of the result shouldn't be affected in this case.
It also follows that the error occurs in large number ranges, in other ranges not and in sub-ranges alternating.
Exactly the same issue in public static Int128 operator %(Int128 left, Int128 right)
.
As reference, to reproduce and test the following code can be used: Test System.Int128 functions, operator and INumber implementation.
A template solution for arbitrary number type for NET7 is used, which of course also supports int128.
An correct implementation for multiplication and remainder can be taken from there.
The tests also show that all other System.Int128
functions and operators handle the overflows correctly.
Reproduction Steps
var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100
Expected behavior
var a = (Int128.MaxValue - 10) * +100; // -1100
var b = (Int128.MaxValue - 10) * -100; // +1100
Actual behavior
var a = (Int128.MaxValue - 10) * +100; // -1100 ok
var b = (Int128.MaxValue - 10) * -100; // -170141183460469231731687303715884104628 wrong, should be +1100
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
No response