Skip to content

Commit 40b6ae7

Browse files
committed
[GR-10284] Math.trunc function is not implemented.
1 parent aaf95f1 commit 40b6ae7

File tree

7 files changed

+133
-0
lines changed

7 files changed

+133
-0
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_int.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,52 @@ def subclassTest(number):
249249
subclassTest(9)
250250
subclassTest(6227020800)
251251
subclassTest(9999992432902008176640000999999)
252+
253+
class MyTrunc:
254+
def __trunc__(self):
255+
return 1972
256+
class MyIntTrunc:
257+
def __trunc__(self):
258+
return 1972
259+
def __int__(self):
260+
return 66
261+
262+
def test_trunc():
263+
def builtinTest(number):
264+
a = int(number)
265+
b = a.__trunc__()
266+
assert a == b
267+
assert a is b
268+
assert type(a) == int
269+
assert type(b) == int
270+
271+
builtinTest(-9)
272+
builtinTest(0)
273+
builtinTest(9)
274+
builtinTest(6227020800)
275+
builtinTest(9999992432902008176640000999999)
276+
277+
assert True.__trunc__() == 1
278+
assert False.__trunc__() == 0
279+
280+
assert int(MyTrunc()) == 1972
281+
assert int(MyIntTrunc()) == 66
282+
283+
def test_trunc_subclass():
284+
def subclassTest(number):
285+
a = MyInt(number)
286+
b = a.__trunc__()
287+
assert a == b
288+
assert a is not b
289+
assert type(a) == MyInt
290+
assert type(b) == int
291+
292+
subclassTest(-9)
293+
subclassTest(0)
294+
subclassTest(9)
295+
subclassTest(6227020800)
296+
subclassTest(9999992432902008176640000999999)
297+
298+
assert MyInt(MyTrunc()) == 1972
299+
assert MyInt(MyIntTrunc()) == 66
300+

graalpython/com.oracle.graal.python.test/src/tests/test_math.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,3 +447,29 @@ class II(int):
447447
self.assertEqual(math.ldexp(FF(10), II(12)), 40960.0)
448448
self.assertRaises(TypeError, math.ldexp, 'Hello', 1000000)
449449
self.assertRaises(TypeError, math.ldexp, 1, 'Hello')
450+
451+
def test_trunc(self):
452+
self.assertEqual(math.trunc(1), 1)
453+
self.assertEqual(math.trunc(-1), -1)
454+
self.assertEqual(type(math.trunc(1)), int)
455+
self.assertEqual(type(math.trunc(1.5)), int)
456+
self.assertEqual(math.trunc(1.5), 1)
457+
self.assertEqual(math.trunc(-1.5), -1)
458+
self.assertEqual(math.trunc(1.999999), 1)
459+
self.assertEqual(math.trunc(-1.999999), -1)
460+
self.assertEqual(math.trunc(-0.999999), -0)
461+
self.assertEqual(math.trunc(-100.999), -100)
462+
463+
class TestTrunc(object):
464+
def __trunc__(self):
465+
return 23
466+
467+
class TestNoTrunc(object):
468+
pass
469+
470+
self.assertEqual(math.trunc(TestTrunc()), 23)
471+
472+
self.assertRaises(TypeError, math.trunc)
473+
self.assertRaises(TypeError, math.trunc, 1, 2)
474+
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
475+

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/BuiltinConstructors.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,11 +698,21 @@ Object fail(PythonClass cls, Object arg, Object keywordArg) {
698698
@Specialization(guards = "isNoValue(keywordArg)")
699699
public Object createInt(PythonClass cls, PythonObject obj, PNone keywordArg,
700700
@Cached("create(__INT__)") LookupAndCallUnaryNode callIntNode,
701+
@Cached("create(__TRUNC__)") LookupAndCallUnaryNode callTruncNode,
701702
@Cached("createBinaryProfile()") ConditionProfile isIntProfile) {
702703
try {
704+
// at first try __int__ method
703705
return createInt(cls, callIntNode.executeLong(obj), keywordArg, isIntProfile);
704706
} catch (UnexpectedResultException e) {
705707
Object result = e.getResult();
708+
if (result == PNone.NO_VALUE) {
709+
try {
710+
// now try __trunc__ method
711+
return createInt(cls, callTruncNode.executeLong(obj), keywordArg, isIntProfile);
712+
} catch (UnexpectedResultException ee) {
713+
result = ee.getResult();
714+
}
715+
}
706716
if (result == PNone.NO_VALUE) {
707717
throw raise(TypeError, "an integer is required (got type %p)", obj);
708718
} else if (result instanceof Integer) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/MathModuleBuiltins.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,21 @@ public abstract static class PowNode extends PythonBuiltinNode {
955955
}
956956
}
957957

958+
@Builtin(name = "trunc", fixedNumOfArguments = 1)
959+
@GenerateNodeFactory
960+
public abstract static class TruncNode extends PythonBuiltinNode {
961+
962+
@Specialization
963+
Object trunc(Object obj,
964+
@Cached("create(__TRUNC__)") LookupAndCallUnaryNode callTrunc) {
965+
Object result = callTrunc.executeObject(obj);
966+
if (result == PNone.NO_VALUE) {
967+
raise(TypeError, "type %p doesn't define __trunc__ method", obj);
968+
}
969+
return result;
970+
}
971+
}
972+
958973
@Builtin(name = "atan2", fixedNumOfArguments = 2)
959974
@GenerateNodeFactory
960975
public abstract static class Atan2Node extends PythonBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import static com.oracle.graal.python.nodes.SpecialMethodNames.__STR__;
5555
import static com.oracle.graal.python.nodes.SpecialMethodNames.__SUB__;
5656
import static com.oracle.graal.python.nodes.SpecialMethodNames.__TRUEDIV__;
57+
import static com.oracle.graal.python.nodes.SpecialMethodNames.__TRUNC__;
5758

5859
import java.math.BigDecimal;
5960
import java.math.RoundingMode;
@@ -924,6 +925,31 @@ static abstract class ConjugateNode extends RealNode {
924925

925926
}
926927

928+
@Builtin(name = __TRUNC__, fixedNumOfArguments = 1)
929+
@GenerateNodeFactory
930+
abstract static class TruncNode extends PythonUnaryBuiltinNode {
931+
932+
private int truncate(double value) {
933+
return (int) (value < 0 ? Math.ceil(value) : Math.floor(value));
934+
}
935+
936+
@Specialization
937+
int trunc(double value) {
938+
return truncate(value);
939+
}
940+
941+
@Specialization
942+
int trunc(PFloat pValue) {
943+
double value = pValue.getValue();
944+
if (value == Double.NaN) {
945+
raise(PythonErrorType.ValueError, "cannot convert float NaN to integer");
946+
} else if (value == Double.NEGATIVE_INFINITY || value == Double.POSITIVE_INFINITY) {
947+
raise(PythonErrorType.OverflowError, "cannot convert float infinity to integer");
948+
}
949+
return truncate(value);
950+
}
951+
}
952+
927953
@Builtin(name = __GETFORMAT__, fixedNumOfArguments = 2)
928954
@GenerateNodeFactory
929955
abstract static class GetFormatNode extends PythonUnaryBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,6 +1888,12 @@ int get(@SuppressWarnings("unused") Object self) {
18881888
}
18891889
}
18901890

1891+
@GenerateNodeFactory
1892+
@Builtin(name = SpecialMethodNames.__TRUNC__, fixedNumOfArguments = 1, doc = "Truncating an Integral returns itself.")
1893+
static abstract class TruncNode extends IntNode {
1894+
1895+
}
1896+
18911897
@Builtin(name = SpecialMethodNames.__INT__, fixedNumOfArguments = 1)
18921898
@GenerateNodeFactory
18931899
abstract static class IntNode extends PythonBuiltinNode {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/SpecialMethodNames.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public abstract class SpecialMethodNames {
8989
public static final String __DIV__ = "__div__";
9090
public static final String __MATMUL__ = "__matmul__";
9191
public static final String __TRUEDIV__ = "__truediv__";
92+
public static final String __TRUNC__ = "__trunc__";
9293
public static final String __FLOORDIV__ = "__floordiv__";
9394
public static final String __MOD__ = "__mod__";
9495
public static final String __DIVMOD__ = "__divmod__";

0 commit comments

Comments
 (0)