Skip to content

Commit 9943584

Browse files
skyoxZmatouskozak
authored andcommitted
Fix Int128 checked-convert to signed IntX (dotnet#100342)
* Fix Int128 checked-convert to signed IntX * Simplify implementation
1 parent 517319a commit 9943584

File tree

2 files changed

+60
-40
lines changed
  • src/libraries

2 files changed

+60
-40
lines changed

src/libraries/System.Private.CoreLib/src/System/Int128.cs

+15-40
Original file line numberDiff line numberDiff line change
@@ -262,17 +262,12 @@ public static explicit operator Half(Int128 value)
262262
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
263263
public static explicit operator checked short(Int128 value)
264264
{
265-
if (~value._upper == 0)
266-
{
267-
long lower = (long)value._lower;
268-
return checked((short)lower);
269-
}
270-
271-
if (value._upper != 0)
265+
long lower = (long)value._lower;
266+
if ((long)value._upper != lower >> 63)
272267
{
273268
ThrowHelper.ThrowOverflowException();
274269
}
275-
return checked((short)value._lower);
270+
return checked((short)lower);
276271
}
277272

278273
/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="int" /> value.</summary>
@@ -286,17 +281,12 @@ public static explicit operator checked short(Int128 value)
286281
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
287282
public static explicit operator checked int(Int128 value)
288283
{
289-
if (~value._upper == 0)
290-
{
291-
long lower = (long)value._lower;
292-
return checked((int)lower);
293-
}
294-
295-
if (value._upper != 0)
284+
long lower = (long)value._lower;
285+
if ((long)value._upper != lower >> 63)
296286
{
297287
ThrowHelper.ThrowOverflowException();
298288
}
299-
return checked((int)value._lower);
289+
return checked((int)lower);
300290
}
301291

302292
/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="long" /> value.</summary>
@@ -310,17 +300,12 @@ public static explicit operator checked int(Int128 value)
310300
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
311301
public static explicit operator checked long(Int128 value)
312302
{
313-
if (~value._upper == 0)
314-
{
315-
long lower = (long)value._lower;
316-
return lower;
317-
}
318-
319-
if (value._upper != 0)
303+
long lower = (long)value._lower;
304+
if ((long)value._upper != lower >> 63)
320305
{
321306
ThrowHelper.ThrowOverflowException();
322307
}
323-
return checked((long)value._lower);
308+
return lower;
324309
}
325310

326311
/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="IntPtr" /> value.</summary>
@@ -334,17 +319,12 @@ public static explicit operator checked long(Int128 value)
334319
/// <exception cref="OverflowException"><paramref name="value" /> is not representable by <see cref="Int128" />.</exception>
335320
public static explicit operator checked nint(Int128 value)
336321
{
337-
if (~value._upper == 0)
338-
{
339-
long lower = (long)value._lower;
340-
return checked((nint)lower);
341-
}
342-
343-
if (value._upper != 0)
322+
long lower = (long)value._lower;
323+
if ((long)value._upper != lower >> 63)
344324
{
345325
ThrowHelper.ThrowOverflowException();
346326
}
347-
return checked((nint)value._lower);
327+
return checked((nint)lower);
348328
}
349329

350330
/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="sbyte" /> value.</summary>
@@ -360,17 +340,12 @@ public static explicit operator checked nint(Int128 value)
360340
[CLSCompliant(false)]
361341
public static explicit operator checked sbyte(Int128 value)
362342
{
363-
if (~value._upper == 0)
364-
{
365-
long lower = (long)value._lower;
366-
return checked((sbyte)lower);
367-
}
368-
369-
if (value._upper != 0)
343+
long lower = (long)value._lower;
344+
if ((long)value._upper != lower >> 63)
370345
{
371346
ThrowHelper.ThrowOverflowException();
372347
}
373-
return checked((sbyte)value._lower);
348+
return checked((sbyte)lower);
374349
}
375350

376351
/// <summary>Explicitly converts a 128-bit signed integer to a <see cref="float" /> value.</summary>

src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs

+45
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,51 @@ public static void EqualsTest(Int128 i1, object obj, bool expected)
107107
Assert.Equal(expected, i1.Equals(obj));
108108
}
109109

110+
[Fact]
111+
public static void CheckedConvertToInt64()
112+
{
113+
Assert.Equal(123L, checked((long)new Int128(0, 123)));
114+
Assert.Equal(-123L, checked((long)(Int128)(-123)));
115+
Assert.Throws<OverflowException>(() => checked((long)new Int128(1, 1)));
116+
Assert.Throws<OverflowException>(() => checked((long)new Int128(ulong.MaxValue, 42)));
117+
}
118+
119+
[Fact]
120+
public static void CheckedConvertToInt32()
121+
{
122+
Assert.Equal(123, checked((int)new Int128(0, 123)));
123+
Assert.Equal(-123, checked((int)(Int128)(-123)));
124+
Assert.Throws<OverflowException>(() => checked((int)new Int128(1, 1)));
125+
Assert.Throws<OverflowException>(() => checked((int)new Int128(ulong.MaxValue, 42)));
126+
}
127+
128+
[Fact]
129+
public static void CheckedConvertToInt16()
130+
{
131+
Assert.Equal((short)123, checked((short)new Int128(0, 123)));
132+
Assert.Equal((short)(-123), checked((short)(Int128)(-123)));
133+
Assert.Throws<OverflowException>(() => checked((short)new Int128(1, 1)));
134+
Assert.Throws<OverflowException>(() => checked((short)new Int128(ulong.MaxValue, 42)));
135+
}
136+
137+
[Fact]
138+
public static void CheckedConvertToSByte()
139+
{
140+
Assert.Equal((sbyte)123, checked((sbyte)new Int128(0, 123)));
141+
Assert.Equal((sbyte)(-123), checked((sbyte)(Int128)(-123)));
142+
Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(1, 1)));
143+
Assert.Throws<OverflowException>(() => checked((sbyte)new Int128(ulong.MaxValue, 42)));
144+
}
145+
146+
[Fact]
147+
public static void CheckedConvertToIntPtr()
148+
{
149+
Assert.Equal((nint)123, checked((nint)new Int128(0, 123)));
150+
Assert.Equal((nint)(-123), checked((nint)(Int128)(-123)));
151+
Assert.Throws<OverflowException>(() => checked((nint)new Int128(1, 1)));
152+
Assert.Throws<OverflowException>(() => checked((nint)new Int128(ulong.MaxValue, 42)));
153+
}
154+
110155
public static IEnumerable<object[]> ToString_TestData()
111156
{
112157
foreach (NumberFormatInfo defaultFormat in new[] { null, NumberFormatInfo.CurrentInfo })

0 commit comments

Comments
 (0)