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

Commits on Aug 2, 2016

  1. Copy the full SHA
    3d13c4c View commit details
  2. Copy the full SHA
    18036dd View commit details
Showing with 37 additions and 81 deletions.
  1. +32 −78 truffle/src/main/java/org/jruby/truffle/core/numeric/FloatNodes.java
  2. +5 −3 truffle/src/main/ruby/core/float.rb
110 changes: 32 additions & 78 deletions truffle/src/main/java/org/jruby/truffle/core/numeric/FloatNodes.java
Original file line number Diff line number Diff line change
@@ -12,6 +12,9 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
@@ -28,14 +31,15 @@
import org.jruby.truffle.builtins.CoreMethodArrayArgumentsNode;
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.builtins.PrimitiveNode;
import org.jruby.truffle.core.cast.DefaultValueNodeGen;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;
import org.jruby.truffle.util.DoubleUtils;
import org.jruby.truffle.util.StringUtils;

import java.util.Locale;

@CoreClass("Float")
@@ -627,18 +631,20 @@ public double prevFloat(double value) {

}

@CoreMethod(names = "round", optional = 1)
public abstract static class RoundNode extends CoreMethodArrayArgumentsNode {

@Child private FixnumOrBignumNode fixnumOrBignum;
@NodeChildren({
@NodeChild(value = "n", type = RubyNode.class),
@NodeChild(value = "ndigits", type = RubyNode.class)
})
@Primitive(name = "float_round", lowerFixnum = 1)
public abstract static class FloatRoundPrimitiveNode extends PrimitiveNode {

public RoundNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
fixnumOrBignum = new FixnumOrBignumNode(context, sourceSection);
@CreateCast("ndigits")
public RubyNode coerceDefault(RubyNode ndigits) {
return DefaultValueNodeGen.create(null, null, 0, ndigits);
}

@Specialization(guards = "doubleInIntRange(n)")
public int roundFittingInt(double n, NotProvided ndigits,
@Specialization(guards = { "ndigits == 0", "doubleInIntRange(n)" })
public int roundFittingInt(double n, int ndigits,
@Cached("createBinaryProfile()") ConditionProfile positiveProfile) {
int l = (int) n;
if (positiveProfile.profile(n >= 0.0)) {
@@ -658,9 +664,9 @@ protected boolean doubleInIntRange(double n) {
return Integer.MIN_VALUE < n && n < Integer.MAX_VALUE;
}

@Specialization(guards = "doubleInLongRange(n)")
public long roundFittingLong(double n, NotProvided ndigits,
@Cached("createBinaryProfile()") ConditionProfile positiveProfile) {
@Specialization(guards = { "ndigits == 0", "doubleInLongRange(n)" }, contains = "roundFittingInt")
public long roundFittingLong(double n, int ndigits,
@Cached("createBinaryProfile()") ConditionProfile positiveProfile) {
long l = (long) n;
if (positiveProfile.profile(n >= 0.0)) {
if (n - l >= 0.5) {
@@ -679,10 +685,11 @@ protected boolean doubleInLongRange(double n) {
return Long.MIN_VALUE < n && n < Long.MAX_VALUE;
}

@Specialization
public Object round(double n, NotProvided ndigits,
@Specialization(guards = "ndigits == 0", contains = "roundFittingLong")
public Object round(double n, int ndigits,
@Cached("createBinaryProfile()") ConditionProfile positiveProfile,
@Cached("create()") BranchProfile errorProfile) {
@Cached("create()") BranchProfile errorProfile,
@Cached("new()") FixnumOrBignumNode fixnumOrBignum) {
// Algorithm copied from JRuby - not shared as we want to branch profile it

if (Double.isInfinite(n)) {
@@ -714,13 +721,14 @@ public Object round(double n, NotProvided ndigits,
return fixnumOrBignum.fixnumOrBignum(f);
}

@Specialization(guards = "wasProvided(ndigits)")
public Object round(
VirtualFrame frame,
double n,
Object ndigits,
@Cached("createMethodCall()") CallDispatchHeadNode callNode) {
return callNode.call(frame, n, "round_internal", ndigits);
@Specialization(guards = "ndigits != 0")
public Object roundDigits(double n, int ndigits) {
return null; // Primitive failure
}

@Specialization(guards = "!isInteger(ndigits)")
public Object roundFallback(double n, Object ndigits) {
return null; // Primitive failure
}

}
@@ -860,58 +868,4 @@ public boolean floatSignBit(double value) {

}

@Primitive(name = "float_round")
public static abstract class FloatRoundPrimitiveNode extends PrimitiveArrayArgumentsNode {

@Child private FixnumOrBignumNode fixnumOrBignum;

private final BranchProfile greaterZero = BranchProfile.create();
private final BranchProfile lessZero = BranchProfile.create();

public FloatRoundPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
fixnumOrBignum = new FixnumOrBignumNode(context, sourceSection);
}

@Specialization
public Object round(double n,
@Cached("create()") BranchProfile errorProfile) {
// Algorithm copied from JRuby - not shared as we want to branch profile it

if (Double.isInfinite(n)) {
errorProfile.enter();
throw new RaiseException(coreExceptions().floatDomainError("Infinity", this));
}

if (Double.isNaN(n)) {
errorProfile.enter();
throw new RaiseException(coreExceptions().floatDomainError("NaN", this));
}

double f = n;

if (f > 0.0) {
greaterZero.enter();

f = Math.floor(f);

if (n - f >= 0.5) {
f += 1.0;
}
} else if (f < 0.0) {
lessZero.enter();

f = Math.ceil(f);

if (f - n >= 0.5) {
f -= 1.0;
}
}

return fixnumOrBignum.fixnumOrBignum(f);
}

}


}
8 changes: 5 additions & 3 deletions truffle/src/main/ruby/core/float.rb
Original file line number Diff line number Diff line change
@@ -148,11 +148,13 @@ def rationalize(eps=undefined)
end
end

def round_internal(ndigits=0)
def round(ndigits=0)
Truffle.primitive :float_round

ndigits = Rubinius::Type.coerce_to(ndigits, Integer, :to_int)

if ndigits == 0
return Truffle.invoke_primitive :float_round, self
return self.round
elsif ndigits < 0
return truncate.round ndigits
end
@@ -170,7 +172,7 @@ def round_internal(ndigits=0)
end

f = 10**ndigits
Truffle.invoke_primitive(:float_round, self * f) / f.to_f
(self * f).round / f.to_f
end

def coerce(other)