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: 2ee022d097c1
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5af0ca257bb9
Choose a head ref
  • 3 commits
  • 10 files changed
  • 1 contributor

Commits on Jul 12, 2017

  1. Copy the full SHA
    472599c View commit details
  2. Copy the full SHA
    c52020c View commit details
  3. Update some numeric excludes.

    headius committed Jul 12, 2017
    Copy the full SHA
    5af0ca2 View commit details
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -517,7 +517,7 @@ private IRubyObject op_divide(ThreadContext context, IRubyObject other, boolean
if (slash) {
return RubyFloat.newFloat(runtime, div);
} else {
return RubyNumeric.dbl2num(runtime, div);
return RubyNumeric.dbl2ival(runtime, div);
}
} else {
return coerceBin(context, slash ? sites(context).op_quo : sites(context).div, other);
@@ -701,7 +701,7 @@ public IRubyObject op_pow(ThreadContext context, IRubyObject other) {
if (Double.isInfinite(pow)) {
return RubyFloat.newFloat(runtime, pow);
}
return RubyNumeric.dbl2num(runtime, pow);
return RubyNumeric.dbl2ival(runtime, pow);
}

public final IRubyObject op_pow(final ThreadContext context, final long other) {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -867,7 +867,7 @@ private IRubyObject powerFixnum(ThreadContext context, IRubyObject other) {
return this;
}
if (a == 0) {
return b > 0 ? RubyFixnum.zero(runtime) : RubyNumeric.dbl2num(runtime, 1.0 / 0.0);
return b > 0 ? RubyFixnum.zero(runtime) : RubyNumeric.dbl2ival(runtime, 1.0 / 0.0);
}
if (a == 1) {
return RubyFixnum.one(runtime);
162 changes: 99 additions & 63 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -408,7 +408,7 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
mod += y;
}
final Ruby runtime = context.runtime;
IRubyObject car = dbl2num(runtime, div);
IRubyObject car = dbl2ival(runtime, div);
RubyFloat cdr = RubyFloat.newFloat(runtime, mod);
return RubyArray.newArray(runtime, car, cdr);
default:
@@ -732,7 +732,7 @@ public IRubyObject to_r(ThreadContext context) {

Ruby runtime = context.runtime;

IRubyObject rf = RubyNumeric.dbl2num(runtime, f);
IRubyObject rf = RubyNumeric.dbl2ival(runtime, f);
IRubyObject rn = RubyFixnum.newFixnum(runtime, n);
return f_mul(context, rf, f_expt(context, RubyFixnum.newFixnum(runtime, FLT_RADIX), rn));
}
@@ -762,7 +762,7 @@ public IRubyObject rationalize(ThreadContext context, IRubyObject[] args) {
long n = exp[0] - DBL_MANT_DIG;


IRubyObject rf = RubyNumeric.dbl2num(runtime, f);
IRubyObject rf = RubyNumeric.dbl2ival(runtime, f);
IRubyObject rn = RubyFixnum.newFixnum(runtime, n);

if (f_zero_p(context, rf) || !(f_negative_p(context, rn) || f_zero_p(context, rn)))
@@ -853,7 +853,7 @@ private static boolean floatInvariantRound(Ruby runtime, double number, int ndig

if (ndigits < - (binexp[0] > 0 ? binexp[0] / 3 + 1 : binexp[0] / 4)) {
num[0] = RubyFixnum.zero(runtime);
return false;
return true;
}

return false;
@@ -902,7 +902,7 @@ public IRubyObject ceil(ThreadContext context, IRubyObject digits) {
@Override
@JRubyMethod(name = "round")
public IRubyObject round(ThreadContext context) {
return roundShared(context, RoundingMode.HALF_UP, 0, context.nil);
return roundShared(context, RoundingMode.HALF_UP, 0);
}

/**
@@ -911,17 +911,17 @@ public IRubyObject round(ThreadContext context) {
@JRubyMethod(name = "round")
public IRubyObject round(ThreadContext context, IRubyObject arg0) {
Ruby runtime = context.runtime;
double digits = 0;
int digits = 0;

// options (only "half" right now)
IRubyObject opts = ArgsUtil.getOptionsArg(runtime, arg0);
if (opts.isNil()) {
digits = num2long(arg0);
digits = num2int(arg0);
}

RoundingMode roundingMode = getRoundingMode(context, opts);

return roundShared(context, roundingMode, digits, opts);
return roundShared(context, roundingMode, digits);
}

/**
@@ -930,32 +930,29 @@ public IRubyObject round(ThreadContext context, IRubyObject arg0) {
@JRubyMethod(name = "round")
public IRubyObject round(ThreadContext context, IRubyObject _digits, IRubyObject _opts) {
Ruby runtime = context.runtime;
double digits = 0;
int digits = 0;

// options (only "half" right now)
IRubyObject opts = ArgsUtil.getOptionsArg(runtime, _opts);
digits = num2long(_digits);
digits = num2int(_digits);

RoundingMode roundingMode = getRoundingMode(context, opts);

return roundShared(context, roundingMode, digits, opts);
return roundShared(context, roundingMode, digits);
}

private IRubyObject roundShared(ThreadContext context, RoundingMode roundingMode, double digits, IRubyObject opts) {
Ruby runtime = context.runtime;
double magnifier = Math.pow(10.0, Math.abs(digits));
double number = value;
private IRubyObject roundShared(ThreadContext context, RoundingMode roundingMode, int ndigits) {
double number, f, x;

if (Double.isInfinite(value)) {
if (digits <= 0) throw runtime.newFloatDomainError(value < 0 ? "-Infinity" : "Infinity");
if (ndigits <= 0) throw context.runtime.newFloatDomainError(value < 0 ? "-Infinity" : "Infinity");
return this;
}

if (Double.isNaN(value)) {
if (digits <= 0) throw runtime.newFloatDomainError("NaN");
if (Double.isInfinite(value)) {
if (ndigits <= 0) throw context.runtime.newFloatDomainError("NaN");
return this;
}

double binexp;
// Missing binexp values for NaN and (-|+)Infinity. frexp man page just says unspecified.
if (value == 0) {
@@ -964,61 +961,100 @@ private IRubyObject roundShared(ThreadContext context, RoundingMode roundingMode
binexp = Math.ceil(Math.log(value)/Math.log(2));
}

// MRI flo_round logic to deal with huge precision numbers.
if (digits >= (DIG+2) - (binexp > 0 ? binexp / 4 : binexp / 3 - 1)) {
return RubyFloat.newFloat(runtime, number);
if (ndigits < 0) {
return ((RubyInteger) truncate(context)).round(context, ndigits);
}
if (digits < -(binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
return dbl2num(runtime, (long) 0);
number = value;
if (ndigits == 0) {
x = doRound(context, roundingMode, number, 1.0);
return dbl2ival(context.runtime, x);
}
RubyNumeric[] num = {this};
if (floatInvariantRound(context.runtime, number, ndigits, num)) return num[0];
f = Math.pow(10, ndigits);
x = doRound(context, roundingMode, number, f);
return dbl2num(context.runtime, x / f);
}

if (Double.isInfinite(magnifier)) {
if (digits < 0) number = 0;
} else {
if (digits < 0) {
number /= magnifier;
} else if (digits > 0){
number *= magnifier;
}

double signum = Math.signum(number);
double abs = Math.abs(number);
private static double doRound(ThreadContext context, RoundingMode roundingMode, double number, double scale) {
switch (roundingMode) {
case HALF_UP:
return roundHalfUp(number, scale);
case HALF_DOWN:
return roundHalfDown(number, scale);
case HALF_EVEN:
return roundHalfEven(number, scale);
}
throw context.runtime.newArgumentError("invalid rounding mode: " + roundingMode);
}

number = doRound(roundingMode, number, signum, abs);
private static double roundHalfUp(double x, double s) {
double f, xs = x * s;

if (digits < 0) {
number *= magnifier;
} else if (digits > 0){
number /= magnifier;
}
int signum = x >= 0.0 ? 1 : -1;
xs = xs * signum;
f = roundHalfUp(xs);
f = f * signum;
if (s == 1.0) return f;
if (x > 0) {
if ((f + 0.5) / s <= x) f += 1;
x = f;
}
else {
if ((f - 0.5) / s >= x) f -= 1;
x = f;
}
return x;
}

if (digits > 0) {
return RubyFloat.newFloat(runtime, number);
} else {
if (number > Long.MAX_VALUE || number < Long.MIN_VALUE) {
// The only way to get huge precise values with BigDecimal is
// to convert the double to String first.
BigDecimal roundedNumber = new BigDecimal(Double.toString(number));
return RubyBignum.newBignum(runtime, roundedNumber.toBigInteger());
}
return dbl2num(runtime, (long)number);
private static double roundHalfDown(double x, double s) {
double f, xs = x * s;

int signum = x >= 0.0 ? 1 : -1;
xs = xs * signum;
f = roundHalfUp(xs);;
f = f * signum;
if (x > 0) {
if ((f - 0.5) / s >= x) f -= 1;
x = f;
}
else {
if ((f + 0.5) / s <= x) f += 1;
x = f;
}
return x;
}

private static double doRound(RoundingMode roundingMode, double number, double signum, double abs) {
switch (roundingMode) {
case HALF_UP:
number = Math.round(abs) * signum;
break;
case HALF_DOWN:
number = ((int) (abs * 2.0)) / 2.0 * signum;
break;
case HALF_EVEN:
number = Math.rint(abs) * signum;
break;
private static double roundHalfUp(double xs) {
return Math.floor((Math.floor((xs + 0.5) * 2.0)) / 2.0);
}

private static double roundHalfEven(double x, double s) {
double f, d, xs = x * s;

if (x > 0.0) {
f = Math.floor(xs);
d = xs - f;
if (d > 0.5)
d = 1.0;
else if (d == 0.5 || ((double)((f + 0.5) / s) <= x))
d = f % 2.0;
else
d = 0.0;
x = f + d;
}
else if (x < 0.0) {
f = Math.ceil(xs);
d = f - xs;
if (d > 0.5)
d = 1.0;
else if (d == 0.5 || ((double)((f - 0.5) / s) >= x))
d = -f % 2.0;
else
d = 0.0;
x = f - d;
}
return number;
return x;
}

/** flo_is_nan_p
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/RubyInteger.java
Original file line number Diff line number Diff line change
@@ -440,6 +440,10 @@ public IRubyObject round(ThreadContext context) {
@JRubyMethod(name = "round")
public IRubyObject round(ThreadContext context, IRubyObject arg) {
int ndigits = RubyNumeric.num2int(arg);
return round(context, ndigits);
}

public IRubyObject round(ThreadContext context, int ndigits) {
if (ndigits > 0) return RubyKernel.new_float(this, this);
if (ndigits == 0) return this;
Ruby runtime = context.runtime;
15 changes: 4 additions & 11 deletions core/src/main/java/org/jruby/RubyNumeric.java
Original file line number Diff line number Diff line change
@@ -94,7 +94,6 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
public static final double DBL_EPSILON=2.2204460492503131e-16;

private static IRubyObject convertToNum(double val, Ruby runtime) {

if (val >= (double) RubyFixnum.MAX || val < (double) RubyFixnum.MIN) {
return RubyBignum.newBignum(runtime, val);
}
@@ -249,21 +248,15 @@ private static long float2long(RubyFloat flt) {
}
}

/** rb_dbl2big + LONG2FIX at once (numeric.c)
*
/**
* MRI: macro DBL2NUM
*/
public static IRubyObject dbl2num(Ruby runtime, double val) {
if (Double.isInfinite(val)) {
throw runtime.newFloatDomainError(val < 0 ? "-Infinity" : "Infinity");
}
if (Double.isNaN(val)) {
throw runtime.newFloatDomainError("NaN");
}
return convertToNum(val, runtime);
return RubyFloat.newFloat(runtime, val);
}

/**
* MRI: dbl2ival
* MRI: macro DBL2IVAL
*/
public static IRubyObject dbl2ival(Ruby runtime, double val) {
if (fixable(val)) {
3 changes: 0 additions & 3 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -1001,9 +1001,6 @@ private IRubyObject roundHalfEven(ThreadContext context) {
num = (RubyInteger) num.op_uminus(context);
}

num = (RubyInteger) num.op_minus(context, RubyFixnum.one(runtime));
num = (RubyInteger) num.op_idiv(context, den);

num = (RubyInteger) ((RubyInteger) num.op_mul(context, RubyFixnum.two(runtime))).op_plus(context, den);
den = (RubyInteger) den.op_mul(context, RubyFixnum.two(runtime));
qr = (RubyArray) num.divmod(context, den);
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/Sprintf.java
Original file line number Diff line number Diff line change
@@ -703,7 +703,7 @@ else if ((flags & FLAG_MINUS) != 0) {
if (type != ClassIndex.INTEGER) {
switch(type) {
case FLOAT:
arg = RubyNumeric.dbl2num(runtime, ((RubyFloat) arg).getValue());
arg = RubyNumeric.dbl2ival(runtime, ((RubyFloat) arg).getValue());
break;
case STRING:
arg = ((RubyString) arg).stringToInum(0, true);
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/TypeConverter.java
Original file line number Diff line number Diff line change
@@ -384,7 +384,7 @@ public static IRubyObject convertToInteger(ThreadContext context, IRubyObject va
if (base != 0) raiseIntegerBaseError(context);
double value = ((RubyFloat) val).getValue();
if (value <= RubyFixnum.MAX || value >= RubyFixnum.MIN) {
return RubyNumeric.dbl2num(context.runtime, value);
return RubyNumeric.dbl2ival(context.runtime, value);
}
} else if (val instanceof RubyInteger) {
if (base != 0) raiseIntegerBaseError(context);
2 changes: 0 additions & 2 deletions test/mri/excludes/Rational_Test.rb
Original file line number Diff line number Diff line change
@@ -4,6 +4,4 @@
exclude :test_conv, "needs investigation"
exclude :test_marshal, "needs investigation"
exclude :test_power_overflow, "consumes much time and memory on JVM"
exclude :test_power_of_0, "needs investigation"
exclude :test_power_of_1_and_minus_1, "needs investigation"
exclude :test_ratsub, "needs investigation"
3 changes: 1 addition & 2 deletions test/mri/excludes/TestFloat.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
exclude :test_cmp_int, "needs investigation"
exclude :test_Float, "needs investigation"
exclude :test_num2dbl, "needs investigation"
exclude :test_cmp_int, "needs investigation"
exclude :test_strtod, "needs investigation"
exclude :test_to_s, "needs investigation"