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

Commits on Jul 11, 2017

  1. Tag another flip-flop test.

    headius committed Jul 11, 2017
    Copy the full SHA
    dc29976 View commit details
  2. Copy the full SHA
    b710cd3 View commit details
Showing with 44 additions and 14 deletions.
  1. +43 −14 core/src/main/java/org/jruby/RubyFloat.java
  2. +1 −0 test/mri/excludes/TestFlip.rb
57 changes: 43 additions & 14 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ast.util.ArgsUtil;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites.FloatSites;
import org.jruby.runtime.ObjectAllocator;
@@ -844,25 +845,42 @@ public IRubyObject round() {
return dbl2num(getRuntime(), val2dbl());
}

@JRubyMethod(name = "round", optional = 1)
@JRubyMethod(name = "round", optional = 2)
public IRubyObject round(ThreadContext context, IRubyObject[] args) {
if (args.length == 0) return round();
// truncate floats.
double digits = num2long(args[0]);
int argc = args.length;

if (argc == 0) return round();
Ruby runtime = context.runtime;
double digits;

// options (only "half" right now)
IRubyObject opts = ArgsUtil.getOptionsArg(runtime, args);
if (opts.isNil()) {
digits = num2long(args[0]);
} else {
argc--;
if (argc == 0) {
digits = 0;
} else {
digits = num2long(args[argc - 1]);
}
}

double magnifier = Math.pow(10.0, Math.abs(digits));
double number = value;

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

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

IRubyObject halfArg = ArgsUtil.extractKeywordArg(context, "half", opts);

double binexp;
// Missing binexp values for NaN and (-|+)Infinity. frexp man page just says unspecified.
if (value == 0) {
@@ -873,39 +891,50 @@ public IRubyObject round(ThreadContext context, IRubyObject[] args) {

// MRI flo_round logic to deal with huge precision numbers.
if (digits >= (DIG+2) - (binexp > 0 ? binexp / 4 : binexp / 3 - 1)) {
return RubyFloat.newFloat(context.runtime, number);
return RubyFloat.newFloat(runtime, number);
}
if (digits < -(binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
return dbl2num(context.runtime, (long) 0);
return dbl2num(runtime, (long) 0);
}

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

number = Math.round(Math.abs(number))*Math.signum(number);
double signum = Math.signum(number);
double abs = Math.abs(number);
if (halfArg.isNil()) {
number = Math.round(abs) * signum;
} else if (halfArg.asJavaString().equals("even")) {
number = Math.rint(abs) * signum;
} else if (halfArg.asJavaString().equals("up")) {
number = (((int) (abs * 2.0)) / 2.0 + 1) * signum;
} else if (halfArg.asJavaString().equals("down")) {
number = ((int) (abs * 2.0)) / 2.0 * signum;
}

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

if (digits > 0) {
return RubyFloat.newFloat(context.runtime, number);
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(context.runtime, roundedNumber.toBigInteger());
return RubyBignum.newBignum(runtime, roundedNumber.toBigInteger());
}
return dbl2num(context.runtime, (long)number);
return dbl2num(runtime, (long)number);
}
}

1 change: 1 addition & 0 deletions test/mri/excludes/TestFlip.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
exclude :test_flip_flop, "flip/flop syntax unimplemented in JRuby"
exclude :test_input_line_number_range, "needs investigation"
exclude :test_shared_thread, "needs investigation"
exclude :test_shared_eval, "IR already built and possibly fully compiled non-closure scope so we cannot add new flip var nor initialize its flip state by adding instructions"