|
43 | 43 | import com.oracle.graal.python.builtins.objects.ints.PInt;
|
44 | 44 | import com.oracle.graal.python.builtins.objects.tuple.PTuple;
|
45 | 45 | import com.oracle.graal.python.nodes.PBaseNode;
|
| 46 | +import com.oracle.graal.python.nodes.PGuards; |
46 | 47 | import com.oracle.graal.python.nodes.SpecialMethodNames;
|
47 | 48 | import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
|
48 | 49 | import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
|
@@ -129,6 +130,50 @@ public double toDouble(Object x) {
|
129 | 130 | }
|
130 | 131 | }
|
131 | 132 |
|
| 133 | + @TypeSystemReference(PythonArithmeticTypes.class) |
| 134 | + @ImportStatic(MathGuards.class) |
| 135 | + static abstract class ConvertToIntNode extends PBaseNode { |
| 136 | + |
| 137 | + @Child private LookupAndCallUnaryNode callIndexNode; |
| 138 | + |
| 139 | + abstract Object execute(Object x); |
| 140 | + |
| 141 | + public static ConvertToIntNode create() { |
| 142 | + return MathModuleBuiltinsFactory.ConvertToIntNodeGen.create(); |
| 143 | + } |
| 144 | + |
| 145 | + @Specialization |
| 146 | + public long toInt(long x) { |
| 147 | + return x; |
| 148 | + } |
| 149 | + |
| 150 | + @Specialization |
| 151 | + public PInt toInt(PInt x) { |
| 152 | + return x; |
| 153 | + } |
| 154 | + |
| 155 | + @Specialization |
| 156 | + public long toInt(double x) { |
| 157 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 158 | + } |
| 159 | + |
| 160 | + @Specialization(guards = "!isNumber(x)") |
| 161 | + public Object toInt(Object x) { |
| 162 | + if (callIndexNode == null) { |
| 163 | + CompilerDirectives.transferToInterpreterAndInvalidate(); |
| 164 | + callIndexNode = insert(LookupAndCallUnaryNode.create(SpecialMethodNames.__INDEX__)); |
| 165 | + } |
| 166 | + Object result = callIndexNode.executeObject(x); |
| 167 | + if (result == PNone.NONE) { |
| 168 | + throw raise(TypeError, "'%p' object cannot be interpreted as an integer", x); |
| 169 | + } |
| 170 | + if (!PGuards.isInteger(result) && !PGuards.isPInt(result) && !(result instanceof Boolean)) { |
| 171 | + throw raise(TypeError, " __index__ returned non-int (type %p)", result); |
| 172 | + } |
| 173 | + return result; |
| 174 | + } |
| 175 | + } |
| 176 | + |
132 | 177 | public abstract static class MathUnaryBuiltinNode extends PythonUnaryBuiltinNode {
|
133 | 178 |
|
134 | 179 | public void checkMathRangeError(boolean con) {
|
@@ -1003,6 +1048,79 @@ public PTuple frexpO(Object value,
|
1003 | 1048 | }
|
1004 | 1049 | }
|
1005 | 1050 |
|
| 1051 | + @Builtin(name = "gcd", fixedNumOfArguments = 2) |
| 1052 | + @TypeSystemReference(PythonArithmeticTypes.class) |
| 1053 | + @GenerateNodeFactory |
| 1054 | + @ImportStatic(MathGuards.class) |
| 1055 | + public abstract static class GcdNode extends PythonBinaryBuiltinNode { |
| 1056 | + |
| 1057 | + private long count(long a, long b) { |
| 1058 | + if (b == 0) { |
| 1059 | + return a; |
| 1060 | + } |
| 1061 | + return count(b, a % b); |
| 1062 | + } |
| 1063 | + |
| 1064 | + @Specialization |
| 1065 | + long gcd(long x, long y) { |
| 1066 | + return Math.abs(count(x, y)); |
| 1067 | + } |
| 1068 | + |
| 1069 | + @Specialization |
| 1070 | + PInt gcd(long x, PInt y) { |
| 1071 | + return factory().createInt(BigInteger.valueOf(x).gcd(y.getValue())); |
| 1072 | + } |
| 1073 | + |
| 1074 | + @Specialization |
| 1075 | + PInt gcd(PInt x, long y) { |
| 1076 | + return factory().createInt(x.getValue().gcd(BigInteger.valueOf(y))); |
| 1077 | + } |
| 1078 | + |
| 1079 | + @Specialization |
| 1080 | + PInt gcd(PInt x, PInt y) { |
| 1081 | + return factory().createInt(x.getValue().gcd(y.getValue())); |
| 1082 | + } |
| 1083 | + |
| 1084 | + @Specialization |
| 1085 | + int gcd(double x, double y) { |
| 1086 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 1087 | + } |
| 1088 | + |
| 1089 | + @Specialization |
| 1090 | + int gcd(long x, double y) { |
| 1091 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 1092 | + } |
| 1093 | + |
| 1094 | + @Specialization |
| 1095 | + int gcd(double x, long y) { |
| 1096 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 1097 | + } |
| 1098 | + |
| 1099 | + @Specialization |
| 1100 | + int gcd(double x, PInt y) { |
| 1101 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 1102 | + } |
| 1103 | + |
| 1104 | + @Specialization |
| 1105 | + int gcd(PInt x, double y) { |
| 1106 | + throw raise(TypeError, "'float' object cannot be interpreted as an integer"); |
| 1107 | + } |
| 1108 | + |
| 1109 | + @Specialization(guards = "!isNumber(x) || !isNumber(y)") |
| 1110 | + Object gcd(Object x, Object y, |
| 1111 | + @Cached("create()") ConvertToIntNode xConvert, |
| 1112 | + @Cached("create()") ConvertToIntNode yConvert, |
| 1113 | + @Cached("create()") GcdNode recursiveNode) { |
| 1114 | + Object xValue = xConvert.execute(x); |
| 1115 | + Object yValue = yConvert.execute(y); |
| 1116 | + return recursiveNode.execute(xValue, yValue); |
| 1117 | + } |
| 1118 | + |
| 1119 | + public static GcdNode create() { |
| 1120 | + return MathModuleBuiltinsFactory.GcdNodeFactory.create(); |
| 1121 | + } |
| 1122 | + } |
| 1123 | + |
1006 | 1124 | @Builtin(name = "acos", fixedNumOfArguments = 1, doc = "Return the arc cosine (measured in radians) of x.")
|
1007 | 1125 | @GenerateNodeFactory
|
1008 | 1126 | public abstract static class AcosNode extends MathDoubleUnaryBuiltinNode {
|
|
0 commit comments