Skip to content

Commit 614b2d8

Browse files
committed
GR-13915: Strength reduction on BigInteger multiplication
- relevant unittest
1 parent ef596d3 commit 614b2d8

File tree

2 files changed

+24
-4
lines changed
  • graalpython
    • com.oracle.graal.python.test/src/tests
    • com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints

2 files changed

+24
-4
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ def test_boolean2int():
6767
assert int(False) == 0
6868

6969

70+
def test_bigint_mul():
71+
assert 99999937497465632974931 * 1223432423545234234123123 == 122343165886896325043539375228725106116626429513
72+
assert 99999937497465632974931 * (2**100) == 126764980791447734004805377032945185921379990352429056
73+
74+
7075
def test_int_from_custom():
7176
class CustomInt4():
7277
def __int__(self):

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

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import com.oracle.graal.python.nodes.util.CastToIndexNode;
8484
import com.oracle.graal.python.runtime.exception.PythonErrorType;
8585
import com.oracle.truffle.api.CompilerDirectives;
86+
import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
8687
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
8788
import com.oracle.truffle.api.dsl.Cached;
8889
import com.oracle.truffle.api.dsl.Fallback;
@@ -613,6 +614,7 @@ PNotImplemented doGeneric(Object left, Object right) {
613614
@GenerateNodeFactory
614615
@TypeSystemReference(PythonArithmeticTypes.class)
615616
abstract static class MulNode extends PythonBinaryBuiltinNode {
617+
@CompilationFinal private ConditionProfile isBigIntPowerOfTwo = ConditionProfile.createBinaryProfile();
616618

617619
@Specialization(rewriteOn = ArithmeticException.class)
618620
int doII(int x, int y) throws ArithmeticException {
@@ -637,27 +639,40 @@ PInt doLLOvf(long x, long y) {
637639
if (((ax | ay) >>> 31 != 0)) {
638640
int leadingZeros = Long.numberOfLeadingZeros(ax) + Long.numberOfLeadingZeros(ay);
639641
if (leadingZeros < 66) {
640-
return factory().createInt(op(BigInteger.valueOf(x), BigInteger.valueOf(y)));
642+
return factory().createInt(mul(BigInteger.valueOf(x), BigInteger.valueOf(y)));
641643
}
642644
}
643645
return factory().createInt(r);
644646
}
645647

646648
@Specialization
647649
PInt doPIntLong(PInt left, long right) {
648-
return factory().createInt(op(left.getValue(), BigInteger.valueOf(right)));
650+
return factory().createInt(mul(left.getValue(), BigInteger.valueOf(right)));
649651
}
650652

651653
@Specialization
652654
PInt doPIntPInt(PInt left, PInt right) {
653-
return factory().createInt(op(left.getValue(), right.getValue()));
655+
return factory().createInt(mul(left.getValue(), right.getValue()));
656+
}
657+
658+
BigInteger mul(BigInteger a, BigInteger b) {
659+
if (isBigIntPowerOfTwo.profile(b.and(b.subtract(BigInteger.ONE)).equals(BigInteger.ZERO))) {
660+
return bigIntegerShift(a, b.getLowestSetBit());
661+
} else {
662+
return bigIntegerMul(a, b);
663+
}
654664
}
655665

656666
@TruffleBoundary
657-
BigInteger op(BigInteger a, BigInteger b) {
667+
BigInteger bigIntegerMul(BigInteger a, BigInteger b) {
658668
return a.multiply(b);
659669
}
660670

671+
@TruffleBoundary
672+
BigInteger bigIntegerShift(BigInteger a, int n) {
673+
return a.shiftLeft(n);
674+
}
675+
661676
@SuppressWarnings("unused")
662677
@Fallback
663678
PNotImplemented doGeneric(Object left, Object right) {

0 commit comments

Comments
 (0)