Skip to content

Commit

Permalink
[release/8.0-staging] Fix Int128 checked-convert to signed IntX (#1…
Browse files Browse the repository at this point in the history
…05998)

* Fix Int128 checked-convert to signed IntX

* Simplify implementation

---------

Co-authored-by: skyoxZ <[email protected]>
  • Loading branch information
github-actions[bot] and skyoxZ authored Aug 8, 2024
1 parent ea63ece commit 58d9176
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 40 deletions.
55 changes: 15 additions & 40 deletions src/libraries/System.Private.CoreLib/src/System/Int128.cs
Original file line number Diff line number Diff line change
Expand Up @@ -262,17 +262,12 @@ public static explicit operator Half(Int128 value)
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
public static explicit operator checked short(Int128 value)
{
if (~value._upper == 0)
{
long lower = (long)value._lower;
return checked((short)lower);
}

if (value._upper != 0)
long lower = (long)value._lower;
if ((long)value._upper != lower >> 63)
{
ThrowHelper.ThrowOverflowException();
}
return checked((short)value._lower);
return checked((short)lower);
}

/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="int" /> value.</summary>
Expand All @@ -286,17 +281,12 @@ public static explicit operator checked short(Int128 value)
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
public static explicit operator checked int(Int128 value)
{
if (~value._upper == 0)
{
long lower = (long)value._lower;
return checked((int)lower);
}

if (value._upper != 0)
long lower = (long)value._lower;
if ((long)value._upper != lower >> 63)
{
ThrowHelper.ThrowOverflowException();
}
return checked((int)value._lower);
return checked((int)lower);
}

/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="long" /> value.</summary>
Expand All @@ -310,17 +300,12 @@ public static explicit operator checked int(Int128 value)
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
public static explicit operator checked long(Int128 value)
{
if (~value._upper == 0)
{
long lower = (long)value._lower;
return lower;
}

if (value._upper != 0)
long lower = (long)value._lower;
if ((long)value._upper != lower >> 63)
{
ThrowHelper.ThrowOverflowException();
}
return checked((long)value._lower);
return lower;
}

/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="IntPtr" /> value.</summary>
Expand All @@ -334,17 +319,12 @@ public static explicit operator checked long(Int128 value)
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
public static explicit operator checked nint(Int128 value)
{
if (~value._upper == 0)
{
long lower = (long)value._lower;
return checked((nint)lower);
}

if (value._upper != 0)
long lower = (long)value._lower;
if ((long)value._upper != lower >> 63)
{
ThrowHelper.ThrowOverflowException();
}
return checked((nint)value._lower);
return checked((nint)lower);
}

/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="sbyte" /> value.</summary>
Expand All @@ -360,17 +340,12 @@ public static explicit operator checked nint(Int128 value)
[CLSCompliant(false)]
public static explicit operator checked sbyte(Int128 value)
{
if (~value._upper == 0)
{
long lower = (long)value._lower;
return checked((sbyte)lower);
}

if (value._upper != 0)
long lower = (long)value._lower;
if ((long)value._upper != lower >> 63)
{
ThrowHelper.ThrowOverflowException();
}
return checked((sbyte)value._lower);
return checked((sbyte)lower);
}

/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="float" /> value.</summary>
Expand Down
45 changes: 45 additions & 0 deletions src/libraries/System.Runtime/tests/System/Int128Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,51 @@ public static void EqualsTest(Int128 i1, object obj, bool expected)
Assert.Equal(expected, i1.Equals(obj));
}

[Fact]
public static void CheckedConvertToInt64()
{
Assert.Equal(123L, checked((long)new Int128(0, 123)));
Assert.Equal(-123L, checked((long)(Int128)(-123)));
Assert.Throws<OverflowException>(() => checked((long)new Int128(1, 1)));
Assert.Throws<OverflowException>(() => checked((long)new Int128(ulong.MaxValue, 42)));
}

[Fact]
public static void CheckedConvertToInt32()
{
Assert.Equal(123, checked((int)new Int128(0, 123)));
Assert.Equal(-123, checked((int)(Int128)(-123)));
Assert.Throws<OverflowException>(() => checked((int)new Int128(1, 1)));
Assert.Throws<OverflowException>(() => checked((int)new Int128(ulong.MaxValue, 42)));
}

[Fact]
public static void CheckedConvertToInt16()
{
Assert.Equal((short)123, checked((short)new Int128(0, 123)));
Assert.Equal((short)(-123), checked((short)(Int128)(-123)));
Assert.Throws<OverflowException>(() => checked((short)new Int128(1, 1)));
Assert.Throws<OverflowException>(() => checked((short)new Int128(ulong.MaxValue, 42)));
}

[Fact]
public static void CheckedConvertToSByte()
{
Assert.Equal((sbyte)123, checked((sbyte)new Int128(0, 123)));
Assert.Equal((sbyte)(-123), checked((sbyte)(Int128)(-123)));
Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(1, 1)));
Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(ulong.MaxValue, 42)));
}

[Fact]
public static void CheckedConvertToIntPtr()
{
Assert.Equal((nint)123, checked((nint)new Int128(0, 123)));
Assert.Equal((nint)(-123), checked((nint)(Int128)(-123)));
Assert.Throws<OverflowException>(() => checked((nint)new Int128(1, 1)));
Assert.Throws<OverflowException>(() => checked((nint)new Int128(ulong.MaxValue, 42)));
}

public static IEnumerable<object[]> ToString_TestData()
{
foreach (NumberFormatInfo defaultFormat in new[] { null, NumberFormatInfo.CurrentInfo })
Expand Down

0 comments on commit 58d9176

Please sign in to comment.