Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f88fd5f311b9
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0f632392bf27
Choose a head ref
  • 2 commits
  • 1 file changed
  • 1 contributor

Commits on Jul 6, 2015

  1. make sure we do not overflow pow with (int) cast

    ... BigInteger#pow(int) throws an ArithmeticException
    kares committed Jul 6, 2015
    Copy the full SHA
    d828f5f View commit details
  2. Copy the full SHA
    0f63239 View commit details
Showing with 23 additions and 15 deletions.
  1. +23 −15 core/src/main/java/org/jruby/RubyBignum.java
38 changes: 23 additions & 15 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -574,33 +574,41 @@ public IRubyObject quo19(ThreadContext context, IRubyObject other) {
*
*/
@JRubyMethod(name = {"**", "power"}, required = 1)
public IRubyObject op_pow(ThreadContext context, IRubyObject other) {
double d;
public IRubyObject op_pow(final ThreadContext context, final IRubyObject other) {
if (other instanceof RubyFixnum) {
RubyFixnum fix = (RubyFixnum) other;
long fixValue = fix.getLongValue();
return op_pow(context, fixValue);
} else if (other instanceof RubyBignum) {
d = ((RubyBignum) other).getDoubleValue();
getRuntime().getWarnings().warn(ID.MAY_BE_TOO_BIG, "in a**b, b may be too big");
}

final double otherValue;
if (other instanceof RubyBignum) {
otherValue = ((RubyBignum) other).getDoubleValue();
warnIfPowExponentTooBig(context, otherValue);
} else if (other instanceof RubyFloat) {
d = ((RubyFloat) other).getDoubleValue();
otherValue = ((RubyFloat) other).getDoubleValue();
} else {
return coerceBin(context, "**", other);

}
return RubyFloat.newFloat(getRuntime(), Math.pow(big2dbl(this), d));
return RubyFloat.newFloat(context.runtime, Math.pow(big2dbl(this), otherValue));
}

public IRubyObject op_pow(ThreadContext context, long other) {
// MRI issuses warning here on (RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024)
if (((value.bitLength() + 7) / 8) * 4 * Math.abs(other) > 1024 * 1024) {
getRuntime().getWarnings().warn(ID.MAY_BE_TOO_BIG, "in a**b, b may be too big");
}
public IRubyObject op_pow(final ThreadContext context, final long other) {
warnIfPowExponentTooBig(context, other);

if (other >= 0) {
return bignorm(getRuntime(), value.pow((int) other)); // num2int is also implemented
} else {
return RubyFloat.newFloat(getRuntime(), Math.pow(big2dbl(this), (double)other));
if ( other <= Integer.MAX_VALUE ) { // only have BigInteger#pow(int)
return bignorm(context.runtime, value.pow((int) other)); // num2int is also implemented
}
}
return RubyFloat.newFloat(context.runtime, Math.pow(big2dbl(this), (double) other));
}

private void warnIfPowExponentTooBig(final ThreadContext context, final double other) {
// MRI issuses warning here on (RBIGNUM(x)->len * SIZEOF_BDIGITS * yy > 1024*1024)
if ( ((value.bitLength() + 7) / 8) * 4 * Math.abs(other) > 1024 * 1024 ) {
context.runtime.getWarnings().warn(ID.MAY_BE_TOO_BIG, "in a**b, b may be too big");
}
}