Skip to content
Merged
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
30 changes: 30 additions & 0 deletions graalpython/com.oracle.graal.python.test/src/tests/test_int.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,41 @@ def test_bigint_mul():
assert 99999937497465632974931 * 1223432423545234234123123 == 122343165886896325043539375228725106116626429513
assert 99999937497465632974931 * (2**100) == 126764980791447734004805377032945185921379990352429056


def test_bigint_mul_powers_of_two():
for shift in (0, 1, 31, 32, 63, 64, 127, 1024, 8192):
power = 1 << shift
for value in (0, 1, -1, 3, -3, (1 << 100) + 7, -((1 << 100) + 7)):
expected = value << shift
assert value * power == expected
assert power * value == expected
assert value * -power == -expected
assert value * (power + 1) == expected + value
assert value * (power - 1) == expected - value
assert value * -(power + 1) == -expected - value


def test_floordiv():
assert 0 // (-92233720368547394651) == 0
assert -234 // (-92233720368547394651) == 0
assert 234 // (-92233720368547394651) == -1


def test_bigint_floordiv_small_quotient():
for bits in (128, 129, 130, 256, 1024, 8192):
for divisor in (1 << (bits - 1),
(1 << (bits - 1)) + (1 << (bits - 32)) - 1,
(1 << bits) - 1):
for quotient in (0, 1, 2, 3, 9, 31, (1 << 30) - 1, 1 << 30, (1 << 31) - 1, 1 << 31):
for remainder in (0, 1, divisor >> 1, divisor - 1):
dividend = quotient * divisor + remainder
negative_quotient = -quotient - (remainder != 0)
assert dividend // divisor == quotient
assert -dividend // -divisor == quotient
assert -dividend // divisor == negative_quotient
assert dividend // -divisor == negative_quotient


def test_pow():
assert 2 ** 10 == 1024
assert type(2 ** -1) is float
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,7 @@ private void initializeTypes() {
}

private void populateBuiltins() {
sysModule = builtinModules.get(T_SYS);
assert PythonBuiltinClassType.verifySlotsConventions(builtins);
for (PythonBuiltins builtin : builtins) {
builtin.initialize(this);
Expand Down Expand Up @@ -1292,7 +1293,6 @@ private void populateBuiltins() {
}

// core machinery
sysModule = builtinModules.get(T_SYS);
sysModules = (PDict) sysModule.getAttribute(T_MODULES);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,9 @@
import com.oracle.graal.python.lib.PyObjectDir;
import com.oracle.graal.python.lib.PyObjectFormat;
import com.oracle.graal.python.lib.PyObjectGetAIter;
import com.oracle.graal.python.lib.PyObjectGetAttr;
import com.oracle.graal.python.lib.PyObjectGetAttrO;
import com.oracle.graal.python.lib.PyObjectGetIter;
import com.oracle.graal.python.lib.PyObjectGetMethod;
import com.oracle.graal.python.lib.PyObjectHashNode;
import com.oracle.graal.python.lib.PyObjectIsInstanceNode;
import com.oracle.graal.python.lib.PyObjectIsSubclassNode;
Expand Down Expand Up @@ -232,6 +232,7 @@
import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode;
import com.oracle.graal.python.nodes.call.CallDispatchers;
import com.oracle.graal.python.nodes.call.CallNode;
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
import com.oracle.graal.python.nodes.call.special.CallUnaryMethodNode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallBinaryNode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
Expand Down Expand Up @@ -283,7 +284,6 @@
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
import com.oracle.truffle.api.RootCallTarget;
Expand Down Expand Up @@ -1575,14 +1575,13 @@ static Object ord(@SuppressWarnings("unused") Object obj,
@GenerateNodeFactory
public abstract static class PrintNode extends PythonBuiltinNode {
@Child private ReadAttributeFromModuleNode readStdout;
@CompilationFinal private PythonModule cachedSys;

@Specialization
@SuppressWarnings("unused")
PNone printNoKeywords(VirtualFrame frame, Object[] values, PNone sep, PNone end, PNone file, PNone flush,
@Bind Node inliningTarget,
@Shared("getWriteMethod") @Cached PyObjectGetAttr getWriteMethod,
@Shared("callWrite") @Cached CallNode callWrite,
@Shared("getWriteMethod") @Cached PyObjectGetMethod getWriteMethod,
@Shared("callWrite") @Cached CallBinaryMethodNode callWrite,
@Shared("callFlush") @Cached PyObjectCallMethodObjArgs callFlush,
@Shared("strNode") @Cached PyObjectStrAsObjectNode strNode) {
Object stdout = getStdout();
Expand All @@ -1596,23 +1595,22 @@ PNone printNoKeywords(VirtualFrame frame, Object[] values, PNone sep, PNone end,
@Specialization(guards = {"!isNone(file)", "!isNoValue(file)"})
static PNone printAllGiven(VirtualFrame frame, Object[] values, TruffleString sep, TruffleString end, Object file, boolean flush,
@Bind Node inliningTarget,
@Shared("getWriteMethod") @Cached PyObjectGetAttr getWriteMethod,
@Shared("callWrite") @Cached CallNode callWrite,
@Shared("getWriteMethod") @Cached PyObjectGetMethod getWriteMethod,
@Shared("callWrite") @Cached CallBinaryMethodNode callWrite,
@Shared("callFlush") @Cached PyObjectCallMethodObjArgs callFlush,
@Shared("strNode") @Cached PyObjectStrAsObjectNode strNode) {
int lastValue = values.length - 1;
// Note: the separate lookup is necessary due to different __getattr__ treatment than
// method lookup
// Resolve write once, before converting the values to strings.
Object writeMethod = getWriteMethod.execute(frame, inliningTarget, file, T_WRITE);
for (int i = 0; i < lastValue; i++) {
callWrite.execute(frame, writeMethod, strNode.execute(frame, inliningTarget, values[i]));
callWrite.execute(frame, writeMethod, sep);
callWrite.executeObject(frame, writeMethod, file, strNode.execute(frame, inliningTarget, values[i]));
callWrite.executeObject(frame, writeMethod, file, sep);
}
LoopNode.reportLoopCount(inliningTarget, values.length == 0 ? 0 : values.length - 1);
if (lastValue >= 0) {
callWrite.execute(frame, writeMethod, strNode.execute(frame, inliningTarget, values[lastValue]));
callWrite.executeObject(frame, writeMethod, file, strNode.execute(frame, inliningTarget, values[lastValue]));
}
callWrite.execute(frame, writeMethod, end);
callWrite.executeObject(frame, writeMethod, file, end);
if (flush) {
callFlush.execute(frame, inliningTarget, file, T_FLUSH);
}
Expand All @@ -1626,8 +1624,8 @@ PNone printGeneric(VirtualFrame frame, Object[] values, Object sepIn, Object end
@Cached CastToTruffleStringNode castSep,
@Cached CastToTruffleStringNode castEnd,
@Cached PyObjectIsTrueNode castFlush,
@Exclusive @Cached PyObjectGetAttr getWriteMethod,
@Exclusive @Cached CallNode callWrite,
@Exclusive @Cached PyObjectGetMethod getWriteMethod,
@Exclusive @Cached CallBinaryMethodNode callWrite,
@Exclusive @Cached PyObjectCallMethodObjArgs callFlush,
@Exclusive @Cached PyObjectStrAsObjectNode strNode,
@Cached PRaiseNode raiseNode) {
Expand Down Expand Up @@ -1665,20 +1663,7 @@ PNone printGeneric(VirtualFrame frame, Object[] values, Object sepIn, Object end
}

private Object getStdout() {
PythonModule sys;
if (getLanguage().isSingleContext()) {
if (cachedSys == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
cachedSys = getContext().lookupBuiltinModule(T_SYS);
}
sys = cachedSys;
} else {
if (cachedSys != null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
cachedSys = null;
}
sys = getContext().lookupBuiltinModule(T_SYS);
}
PythonModule sys = getContext().getSysModule();
if (readStdout == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
readStdout = insert(ReadAttributeFromModuleNode.create());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@

import static com.oracle.graal.python.nodes.BuiltinNames.J_READLINE;
import static com.oracle.graal.python.nodes.BuiltinNames.T_READLINE;
import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS;
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached;
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
Expand Down Expand Up @@ -115,7 +114,7 @@ public void postInitialize(Python3Core core) {
module.setAttribute(T_BACKEND, T_JLINE);
LocalData moduleState = new LocalData();
module.setModuleState(moduleState);
Object consoleHandler = core.lookupBuiltinModule(T_SYS).getAttribute(T__CONSOLE_HANDLER);
Object consoleHandler = core.getSysModule().getAttribute(T__CONSOLE_HANDLER);
if (consoleHandler != PNone.NO_VALUE) {
InteropLibrary lib = InteropLibrary.getUncached(consoleHandler);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDERR;
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDIN;
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDOUT;
import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS;
import static com.oracle.graal.python.nodes.BuiltinNames.T_UNRAISABLEHOOK;
import static com.oracle.graal.python.nodes.BuiltinNames.T___BREAKPOINTHOOK__;
import static com.oracle.graal.python.nodes.BuiltinNames.T___DISPLAYHOOK__;
Expand Down Expand Up @@ -614,7 +613,7 @@ public static PTuple createIntInfo(PythonLanguage language) {

public void postInitialize0(Python3Core core) {
super.postInitialize(core);
PythonModule sys = core.lookupBuiltinModule(T_SYS);
PythonModule sys = core.getSysModule();
PythonContext context = core.getContext();
PythonLanguage language = core.getLanguage();
String[] args = context.getEnv().getApplicationArguments();
Expand Down Expand Up @@ -761,7 +760,7 @@ private static Object[] convertToObjectArray(TruffleString[] arr) {
public void postInitialize(Python3Core core) {
postInitialize0(core);
initStd(core);
PythonModule sys = core.lookupBuiltinModule(T_SYS);
PythonModule sys = core.getSysModule();
core.getContext().registerCApiHook(() -> {
sys.setAttribute(toTruffleStringUncached("_dllhandle_name"), toTruffleStringUncached(core.getContext().getCApiContext().getLibraryName()));
});
Expand All @@ -777,7 +776,7 @@ static void initStd(Python3Core core) {
TruffleString stdioEncoding = gp.getStdIOEncoding();
TruffleString stdioError = gp.getStdIOError();
PosixSupport posixSupport = context.getPosixSupport();
PythonModule sysModule = core.lookupBuiltinModule(T_SYS);
PythonModule sysModule = core.getSysModule();

// Note that stdin is always buffered, this only applies to stdout and stderr
boolean buffering = !context.getOption(PythonOptions.UnbufferedIO);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
import static com.oracle.graal.python.nodes.BuiltinNames.J__WARNINGS;
import static com.oracle.graal.python.nodes.BuiltinNames.T_MODULE;
import static com.oracle.graal.python.nodes.BuiltinNames.T_MODULES;
import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS;
import static com.oracle.graal.python.nodes.BuiltinNames.T__WARNINGS;
import static com.oracle.graal.python.nodes.BuiltinNames.T___MAIN__;
import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___LOADER__;
Expand Down Expand Up @@ -405,7 +404,7 @@ private PDict getSysDict() {
reportPolymorphicSpecialize();
getDictNode = insert(GetOrCreateDictNode.create());
}
return getDictNode.executeCached(getContext().lookupBuiltinModule(T_SYS));
return getDictNode.executeCached(getContext().getSysModule());
}

private PFrame getCallerFrame(VirtualFrame frame, int stackLevel, TruffleString[] skipFilePrefixes) {
Expand Down Expand Up @@ -520,7 +519,7 @@ private static Object getWarningsAttr(VirtualFrame frame, BoundaryCallData bound
return null;
}
} else {
Object sys = context.lookupBuiltinModule(T_SYS);
Object sys = context.getSysModule();
Object modules = lookup.executeCached(frame, sys, T_MODULES);
try {
warningsModule = callMethod.executeCached(frame, modules, T_GET, T_WARNINGS, PNone.NONE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@
import static com.oracle.graal.python.builtins.objects.cext.capi.transitions.ArgDescriptor.PyObjectBorrowed;
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDERR;
import static com.oracle.graal.python.nodes.BuiltinNames.T_STDOUT;
import static com.oracle.graal.python.nodes.BuiltinNames.T_SYS;
import static com.oracle.graal.python.runtime.PythonContext.NATIVE_NULL;

import com.oracle.graal.python.builtins.modules.cext.PythonCextBuiltins.CApiBuiltin;
Expand Down Expand Up @@ -87,7 +86,7 @@ Object getObject(TruffleString name,
@Cached PyObjectLookupAttr lookupNode,
@Cached PyObjectSetAttr setAttrNode) {
try {
PythonModule sys = getCore().lookupBuiltinModule(T_SYS);
PythonModule sys = getCore().getSysModule();
Object value = lookupNode.execute(null, inliningTarget, sys, name);
if (value == PNone.NO_VALUE) {
return NATIVE_NULL;
Expand All @@ -109,7 +108,7 @@ Object getObject(TruffleString name,
private static Object selectOut(int fd) {
CompilerAsserts.neverPartOfCompilation();
Object file;
PythonModule sys = PythonContext.get(null).lookupBuiltinModule(T_SYS);
PythonModule sys = PythonContext.get(null).getSysModule();
if (fd == 0) {
file = sys.getAttribute(T_STDOUT);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,33 @@ static PInt doPiPi(PInt left, PInt right,
static BigInteger op(BigInteger left, BigInteger right) {
// Math.floorDiv for BigInteger
int leftSign = left.signum();
if (leftSign > 0 && right.signum() > 0) {
int rightBits = right.bitLength();
int bitDifference = left.bitLength() - rightBits;
if (rightBits > 128 && bitDifference >= 0 && bitDifference < 31) {
/*
* Keep 32 leading divisor bits and at most 62 dividend bits. If these truncated
* operands are u and v, the exact floor-division quotient is between u / (v + 1) and u / v.
* When both bounds agree, no full-width arithmetic is needed. Otherwise, a single multiplication
* and comparison determine the exact quotient.
*/
int shift = rightBits - 32;
long u = left.shiftRight(shift).longValue();
long v = right.shiftRight(shift).longValue();
long lower = u / (v + 1);
long upper = u / v;
if (lower == upper) {
return BigInteger.valueOf(lower);
} else {
assert upper == lower + 1;
if (left.compareTo(right.multiply(BigInteger.valueOf(upper))) < 0) {
return BigInteger.valueOf(lower);
} else {
return BigInteger.valueOf(upper);
}
}
}
}
if (leftSign == 0 || leftSign == right.signum()) {
return left.divide(right);
}
Expand Down Expand Up @@ -1224,8 +1251,8 @@ static PInt doPIntPInt(PInt left, PInt right,

@TruffleBoundary
public static BigInteger mul(BigInteger a, BigInteger b) {
if (!BigInteger.ZERO.equals(b) && b.and(b.subtract(BigInteger.ONE)).equals(BigInteger.ZERO)) {
return bigIntegerShift(a, b.getLowestSetBit());
if (b.signum() > 0 && b.getLowestSetBit() == b.bitLength() - 1) {
return bigIntegerShift(a, b.bitLength() - 1);
} else {
return bigIntegerMul(a, b);
}
Expand Down
Loading
Loading