Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions eng/scripts/generate_alltypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,17 @@ def is_implicit(self, oty):
[SpecialName]
public static %(type)s %(method_name)s(%(type)s x) => (%(type)s)(%(symbol)s(x));"""

round_method = """
public static object __round__(%(type)s x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (%(type)s.MinValue <= result && result <= %(type)s.MaxValue) {
return unchecked((%(type)s)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}"""

signed_abs = """
[SpecialName]
Expand Down Expand Up @@ -201,6 +212,10 @@ def gen_unaryops(cw, ty):
cw.write(unchecked_cast_method, type=ty.name, method_name="__int__", cast_type=ty.cast_type)
cw.write(unchecked_cast_method, type=ty.name, method_name="__index__", cast_type=ty.cast_type)

if ty.name not in ['Int32']:
cw.write(unchecked_cast_method, type=ty.name, method_name="__round__", cast_type=ty.cast_type)
cw.write(round_method, type=ty.name)

cw.writeline()
cw.enter_block('public static int __hash__(%s x)' % (ty.name))
if ty.max > Int32.MaxValue:
Expand Down
95 changes: 93 additions & 2 deletions src/core/IronPython/Runtime/Operations/IntOps.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
using System.Numerics;
using System.Runtime.CompilerServices;

using IronPython.Runtime.Types;

using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;

using IronPython.Runtime.Types;

#pragma warning disable 675

namespace IronPython.Runtime.Operations {
Expand Down Expand Up @@ -105,6 +105,19 @@ public static object Abs(SByte x) {

public static int __index__(SByte x) => unchecked((int)x);

public static int __round__(SByte x) => unchecked((int)x);

public static object __round__(SByte x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (SByte.MinValue <= result && result <= SByte.MaxValue) {
return unchecked((SByte)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(SByte x) {
if (x == -1) return -2;
return unchecked((int)x);
Expand Down Expand Up @@ -378,6 +391,19 @@ public static object __new__(PythonType cls, object value) {

public static int __index__(Byte x) => unchecked((int)x);

public static int __round__(Byte x) => unchecked((int)x);

public static object __round__(Byte x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (Byte.MinValue <= result && result <= Byte.MaxValue) {
return unchecked((Byte)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(Byte x) {
return unchecked((int)x);
}
Expand Down Expand Up @@ -753,6 +779,19 @@ public static object Abs(Int16 x) {

public static int __index__(Int16 x) => unchecked((int)x);

public static int __round__(Int16 x) => unchecked((int)x);

public static object __round__(Int16 x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (Int16.MinValue <= result && result <= Int16.MaxValue) {
return unchecked((Int16)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(Int16 x) {
if (x == -1) return -2;
return unchecked((int)x);
Expand Down Expand Up @@ -1031,6 +1070,19 @@ public static object __new__(PythonType cls, object value) {

public static int __index__(UInt16 x) => unchecked((int)x);

public static int __round__(UInt16 x) => unchecked((int)x);

public static object __round__(UInt16 x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (UInt16.MinValue <= result && result <= UInt16.MaxValue) {
return unchecked((UInt16)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(UInt16 x) {
return unchecked((int)x);
}
Expand Down Expand Up @@ -1669,6 +1721,19 @@ public static object __new__(PythonType cls, object value) {

public static BigInteger __index__(UInt32 x) => unchecked((BigInteger)x);

public static BigInteger __round__(UInt32 x) => unchecked((BigInteger)x);

public static object __round__(UInt32 x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (UInt32.MinValue <= result && result <= UInt32.MaxValue) {
return unchecked((UInt32)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(UInt32 x) {
return unchecked((int)((x >= int.MaxValue) ? (x % int.MaxValue) : x));
}
Expand Down Expand Up @@ -2054,6 +2119,19 @@ public static object Abs(Int64 x) {

public static BigInteger __index__(Int64 x) => unchecked((BigInteger)x);

public static BigInteger __round__(Int64 x) => unchecked((BigInteger)x);

public static object __round__(Int64 x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (Int64.MinValue <= result && result <= Int64.MaxValue) {
return unchecked((Int64)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(Int64 x) {
if (x < 0) {
if (x == long.MinValue) return -2;
Expand Down Expand Up @@ -2330,6 +2408,19 @@ public static object __new__(PythonType cls, object value) {

public static BigInteger __index__(UInt64 x) => unchecked((BigInteger)x);

public static BigInteger __round__(UInt64 x) => unchecked((BigInteger)x);

public static object __round__(UInt64 x, object ndigits) {
var result = BigIntegerOps.__round__(x, ndigits);
if (UInt64.MinValue <= result && result <= UInt64.MaxValue) {
return unchecked((UInt64)result);
}
if (int.MinValue <= result && result <= int.MaxValue) {
return (int)result;
}
return result;
}

public static int __hash__(UInt64 x) {
return unchecked((int)((x >= int.MaxValue) ? (x % int.MaxValue) : x));
}
Expand Down
34 changes: 34 additions & 0 deletions tests/suite/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1735,4 +1735,38 @@ def test_errors_string_format(self):
import System
self.assertRaises(KeyError, lambda: System.DayOfWeek["{0}"])

@skipUnlessIronPython()
def test_ipy3_gh1977(self):
# https://github.com/IronLanguages/ironpython3/issues/1977
import System

res = round(System.Single(1.23))
self.assertTrue(isinstance(res, int))
self.assertEqual(res, 1)

res = round(System.Single(1.23), 2)
self.assertTrue(isinstance(res, System.Single))
self.assertEqual(res, System.Single(1.23))

for t in [System.SByte, System.Byte, System.Int16, System.UInt16, System.Int32, System.UInt32, System.Int64, System.UInt64]:
# round with no ndigits is expected to return an int
res = round(t.MaxValue)
self.assertTrue(isinstance(res, int))
self.assertEqual(res, t.MaxValue)

# round with ndigits specified is expected to return the same type as the input
res = round(t.MaxValue, 2)
self.assertTrue(isinstance(res, t))
self.assertEqual(res, t.MaxValue)

# on overflow, return an int
ndigits = 1 - len(str(int(t.MaxValue)))
expected = round(int(t.MaxValue), ndigits)
res = round(t.MaxValue, ndigits)
self.assertEqual(res, expected)
if expected > int(t.MaxValue):
self.assertTrue(isinstance(res, int))
else:
self.assertTrue(isinstance(res, t))

run_test(__name__)