42
42
import com .oracle .graal .python .builtins .objects .ints .PInt ;
43
43
import com .oracle .graal .python .builtins .objects .tuple .PTuple ;
44
44
import com .oracle .graal .python .nodes .PNode ;
45
+ import com .oracle .graal .python .nodes .SpecialMethodNames ;
45
46
import com .oracle .graal .python .nodes .call .special .LookupAndCallUnaryNode ;
46
47
import com .oracle .graal .python .nodes .function .PythonBuiltinNode ;
47
48
import com .oracle .graal .python .nodes .function .builtins .PythonUnaryBuiltinNode ;
48
49
import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
49
50
import com .oracle .graal .python .runtime .exception .PythonErrorType ;
50
51
import com .oracle .graal .python .runtime .object .PythonObjectFactory ;
52
+ import com .oracle .truffle .api .CompilerDirectives ;
51
53
import com .oracle .truffle .api .CompilerDirectives .CompilationFinal ;
52
54
import com .oracle .truffle .api .CompilerDirectives .TruffleBoundary ;
53
55
import com .oracle .truffle .api .dsl .Cached ;
@@ -1152,6 +1154,34 @@ protected static IsInfNode create() {
1152
1154
@ GenerateNodeFactory
1153
1155
public abstract static class LogNode extends PythonUnaryBuiltinNode {
1154
1156
1157
+ @ Child private LookupAndCallUnaryNode valueDispatchNode ;
1158
+ @ Child private LookupAndCallUnaryNode baseDispatchNode ;
1159
+ @ Child private LogNode recLogNode ;
1160
+
1161
+ private LookupAndCallUnaryNode getValueDispatchNode () {
1162
+ if (valueDispatchNode == null ) {
1163
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
1164
+ valueDispatchNode = insert (LookupAndCallUnaryNode .create (SpecialMethodNames .__FLOAT__ ));
1165
+ }
1166
+ return valueDispatchNode ;
1167
+ }
1168
+
1169
+ private LookupAndCallUnaryNode getBaseDispatchNode () {
1170
+ if (baseDispatchNode == null ) {
1171
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
1172
+ baseDispatchNode = insert (LookupAndCallUnaryNode .create (SpecialMethodNames .__FLOAT__ ));
1173
+ }
1174
+ return baseDispatchNode ;
1175
+ }
1176
+
1177
+ private double executeRecursiveLogNode (Object value , Object base ) {
1178
+ if (recLogNode == null ) {
1179
+ CompilerDirectives .transferToInterpreterAndInvalidate ();
1180
+ recLogNode = insert (LogNode .create ());
1181
+ }
1182
+ return recLogNode .executeObject (value , base );
1183
+ }
1184
+
1155
1185
public abstract double executeObject (Object value , Object base );
1156
1186
1157
1187
private static final double LOG2 = Math .log (2.0 );
@@ -1179,7 +1209,7 @@ private double countBase(BigInteger base, ConditionProfile divByZero) {
1179
1209
}
1180
1210
return logBase ;
1181
1211
}
1182
-
1212
+
1183
1213
@ Specialization
1184
1214
public double log (long value , @ SuppressWarnings ("unused" ) PNone novalue ,
1185
1215
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ) {
@@ -1189,39 +1219,35 @@ public double log(long value, @SuppressWarnings("unused") PNone novalue,
1189
1219
@ Specialization
1190
1220
public double logDN (double value , @ SuppressWarnings ("unused" ) PNone novalue ,
1191
1221
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ) {
1192
- if (doNotFit .profile (value < 0 )) {
1193
- throw raise (ValueError , "math domain error" );
1194
- }
1222
+ raiseMathError (doNotFit , value < 0 );
1195
1223
return Math .log (value );
1196
1224
}
1197
1225
1198
1226
@ Specialization
1199
1227
@ TruffleBoundary
1200
- public double log (PInt value , @ SuppressWarnings ("unused" ) PNone novalue ,
1228
+ public double logPIN (PInt value , @ SuppressWarnings ("unused" ) PNone novalue ,
1201
1229
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ) {
1202
1230
BigInteger bValue = value .getValue ();
1203
- if (doNotFit .profile (bValue .compareTo (BigInteger .ZERO ) == -1 )) {
1204
- throw raise (ValueError , "math domain error" );
1205
- }
1231
+ raiseMathError (doNotFit , bValue .compareTo (BigInteger .ZERO ) == -1 );
1206
1232
return logBigInteger (bValue );
1207
1233
}
1208
1234
1209
1235
@ Specialization
1210
- public double log (long value , long base ,
1236
+ public double logLL (long value , long base ,
1211
1237
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1212
1238
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1213
1239
return logDD (value , base , doNotFit , divByZero );
1214
1240
}
1215
1241
1216
1242
@ Specialization
1217
- public double log (double value , long base ,
1243
+ public double logDL (double value , long base ,
1218
1244
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1219
1245
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1220
1246
return logDD (value , base , doNotFit , divByZero );
1221
1247
}
1222
1248
1223
1249
@ Specialization
1224
- public double log (long value , double base ,
1250
+ public double logLD (long value , double base ,
1225
1251
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1226
1252
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1227
1253
return logDD (value , base , doNotFit , divByZero );
@@ -1231,28 +1257,24 @@ public double log(long value, double base,
1231
1257
public double logDD (double value , double base ,
1232
1258
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1233
1259
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1234
- if (doNotFit .profile (value < 0 || base <= 0 )) {
1235
- throw raise (ValueError , "math domain error" );
1236
- }
1260
+ raiseMathError (doNotFit , value < 0 || base <= 0 );
1237
1261
double logBase = countBase (base , divByZero );
1238
1262
return Math .log (value ) / logBase ;
1239
1263
}
1240
1264
1241
1265
@ Specialization
1242
1266
@ TruffleBoundary
1243
- public double logDD (double value , PInt base ,
1267
+ public double logDPI (double value , PInt base ,
1244
1268
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1245
1269
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1246
1270
BigInteger bBase = base .getValue ();
1247
- if (doNotFit .profile (value < 0 || bBase .compareTo (BigInteger .ZERO ) <= 0 )) {
1248
- throw raise (ValueError , "math domain error" );
1249
- }
1271
+ raiseMathError (doNotFit , value < 0 || bBase .compareTo (BigInteger .ZERO ) <= 0 );
1250
1272
double logBase = countBase (bBase , divByZero );
1251
1273
return Math .log (value ) / logBase ;
1252
1274
}
1253
1275
1254
1276
@ Specialization
1255
- public double log (PInt value , long base ,
1277
+ public double logPIL (PInt value , long base ,
1256
1278
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1257
1279
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1258
1280
return logPID (value , base , doNotFit , divByZero );
@@ -1264,122 +1286,82 @@ public double logPID(PInt value, double base,
1264
1286
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1265
1287
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1266
1288
BigInteger bValue = value .getValue ();
1267
- if (doNotFit .profile (bValue .compareTo (BigInteger .ZERO ) == -1 || base <= 0 )) {
1268
- throw raise (ValueError , "math domain error" );
1269
- }
1289
+ raiseMathError (doNotFit , bValue .compareTo (BigInteger .ZERO ) == -1 || base <= 0 );
1270
1290
double logBase = countBase (base , divByZero );
1271
1291
return logBigInteger (bValue ) / logBase ;
1272
1292
}
1273
1293
1274
1294
@ Specialization
1275
1295
@ TruffleBoundary
1276
- public double log (long value , PInt base ,
1296
+ public double logLPI (long value , PInt base ,
1277
1297
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1278
1298
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1279
1299
BigInteger bBase = base .getValue ();
1280
- if (doNotFit .profile (value < 0 || bBase .compareTo (BigInteger .ZERO ) <= 0 )) {
1281
- throw raise (ValueError , "math domain error" );
1282
- }
1300
+ raiseMathError (doNotFit , value < 0 || bBase .compareTo (BigInteger .ZERO ) <= 0 );
1283
1301
double logBase = countBase (bBase , divByZero );
1284
1302
return Math .log (value ) / logBase ;
1285
1303
}
1286
1304
1287
1305
@ Specialization
1288
1306
@ TruffleBoundary
1289
- public double log (PInt value , PInt base ,
1307
+ public double logPIPI (PInt value , PInt base ,
1290
1308
@ Cached ("createBinaryProfile()" ) ConditionProfile doNotFit ,
1291
1309
@ Cached ("createBinaryProfile()" ) ConditionProfile divByZero ) {
1292
1310
BigInteger bValue = value .getValue ();
1293
1311
BigInteger bBase = base .getValue ();
1294
- if (doNotFit .profile (bValue .compareTo (BigInteger .ZERO ) == -1 || bBase .compareTo (BigInteger .ZERO ) <= 0 )) {
1295
- throw raise (ValueError , "math domain error" );
1296
- }
1312
+ raiseMathError (doNotFit , bValue .compareTo (BigInteger .ZERO ) == -1 || bBase .compareTo (BigInteger .ZERO ) <= 0 );
1297
1313
double logBase = countBase (bBase , divByZero );
1298
1314
return logBigInteger (bValue ) / logBase ;
1299
1315
}
1300
1316
1301
1317
@ Specialization (guards = "!isNumber(value)" )
1302
- public double log (Object value , @ SuppressWarnings ("unused" ) PNone novalue ,
1303
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1304
- @ Cached ("create()" ) LogNode logNode ) {
1305
- Object result = dispatchFloat .executeObject (value );
1306
- if (result == PNone .NO_VALUE ) {
1307
- throw raise (TypeError , "must be real number, not %p" , value );
1308
- }
1309
- return logNode .executeObject (result , novalue );
1318
+ public double logO (Object value , @ SuppressWarnings ("unused" ) PNone novalue ,
1319
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumber ) {
1320
+ Object result = getRealNumber (value , getValueDispatchNode (), notNumber );
1321
+ return executeRecursiveLogNode (result , novalue );
1310
1322
}
1311
1323
1312
- @ Specialization (guards = "!isNumber(value)" )
1313
- public double log (Object value , long base ,
1314
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1315
- @ Cached ("create()" ) LogNode logNode ) {
1316
- return logOD (value , base , dispatchFloat , logNode );
1317
- }
1318
-
1319
- @ Specialization (guards = "!isNumber(value)" )
1320
- public double logOD (Object value , double base ,
1321
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1322
- @ Cached ("create()" ) LogNode logNode ) {
1323
- Object result = dispatchFloat .executeObject (value );
1324
- if (result == PNone .NO_VALUE ) {
1325
- throw raise (TypeError , "must be real number, not %p" , value );
1326
- }
1327
- return logNode .executeObject (result , base );
1328
- }
1329
-
1330
- @ Specialization (guards = "!isNumber(value)" )
1331
- public double log (Object value , PInt base ,
1332
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1333
- @ Cached ("create()" ) LogNode logNode ) {
1334
- Object result = dispatchFloat .executeObject (value );
1335
- if (result == PNone .NO_VALUE ) {
1336
- throw raise (TypeError , "must be real number, not %p" , value );
1337
- }
1338
- return logNode .executeObject (result , base );
1339
- }
1340
-
1341
- @ Specialization (guards = {"!isNumber(value)" , "!isNumber(base)" })
1342
- public double log (Object value , Object base ,
1343
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1344
- @ Cached ("create()" ) LogNode logNode ) {
1345
- Object resultValue = dispatchFloat .executeObject (value );
1346
- if (resultValue == PNone .NO_VALUE ) {
1347
- throw raise (TypeError , "must be real number, not %p" , value );
1348
- }
1349
- Object resultBase = dispatchFloat .executeObject (base );
1350
- if (resultBase == PNone .NO_VALUE ) {
1351
- throw raise (TypeError , "must be real number, not %p" , base );
1352
- }
1353
- return logNode .executeObject (resultValue , resultBase );
1324
+ @ Specialization (guards = {"!isNumber(value)" , "!isNoValue(base)" })
1325
+ public double logOO (Object value , Object base ,
1326
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumberValue ,
1327
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumberBase ) {
1328
+ Object resultValue = getRealNumber (value , getValueDispatchNode (), notNumberValue );
1329
+ Object resultBase = getRealNumber (base , getBaseDispatchNode (), notNumberBase );
1330
+ return executeRecursiveLogNode (resultValue , resultBase );
1354
1331
}
1355
1332
1356
1333
@ Specialization (guards = {"!isNumber(base)" })
1357
- public double log (long value , Object base ,
1358
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1359
- @ Cached ("create()" ) LogNode logNode ) {
1360
- return logDO (value , base , dispatchFloat , logNode );
1334
+ public double logLO (long value , Object base ,
1335
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumberBase ) {
1336
+ return logDO (value , base , notNumberBase );
1361
1337
}
1362
1338
1363
1339
@ Specialization (guards = {"!isNumber(base)" })
1364
1340
public double logDO (double value , Object base ,
1365
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1366
- @ Cached ("create()" ) LogNode logNode ) {
1367
- Object resultBase = dispatchFloat .executeObject (base );
1368
- if (resultBase == PNone .NO_VALUE ) {
1369
- throw raise (TypeError , "must be real number, not %p" , base );
1370
- }
1371
- return logNode .executeObject (value , resultBase );
1341
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumberBase ) {
1342
+ Object resultBase = getRealNumber (base , getBaseDispatchNode (), notNumberBase );
1343
+ return executeRecursiveLogNode (value , resultBase );
1372
1344
}
1373
1345
1374
1346
@ Specialization (guards = {"!isNumber(base)" })
1375
- public double log (PInt value , Object base ,
1376
- @ Cached ("create(__FLOAT__)" ) LookupAndCallUnaryNode dispatchFloat ,
1377
- @ Cached ("create()" ) LogNode logNode ) {
1378
- Object resultBase = dispatchFloat .executeObject (base );
1379
- if (resultBase == PNone .NO_VALUE ) {
1380
- throw raise (TypeError , "must be real number, not %p" , base );
1347
+ public double logPIO (PInt value , Object base ,
1348
+ @ Cached ("createBinaryProfile()" ) ConditionProfile notNumberBase ) {
1349
+ Object resultBase = getRealNumber (base , getBaseDispatchNode (), notNumberBase );
1350
+ return executeRecursiveLogNode (value , resultBase );
1351
+ }
1352
+
1353
+ private void raiseMathError (ConditionProfile doNotFit , boolean con ) {
1354
+ if (doNotFit .profile (con )) {
1355
+ throw raise (ValueError , "math domain error" );
1381
1356
}
1382
- return logNode .executeObject (value , resultBase );
1357
+ }
1358
+
1359
+ private Object getRealNumber (Object object , LookupAndCallUnaryNode dispatchNode , ConditionProfile isNotRealNumber ) {
1360
+ Object result = dispatchNode .executeObject (object );
1361
+ if (result == PNone .NO_VALUE ) {
1362
+ throw raise (TypeError , "must be real number, not %p" , object );
1363
+ }
1364
+ return result ;
1383
1365
}
1384
1366
1385
1367
public static LogNode create () {
0 commit comments