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

Commits on Dec 18, 2014

  1. [Truffle] Be tighter with the bounds when comparing double to integer…

    … types to account for loss of precision.
    nirvdrum committed Dec 18, 2014
    Copy the full SHA
    53e64de View commit details
  2. [Truffle] At this point we've already determined we can't cast to lon…

    …g without losing precision, so use BigDecimal to preserve data.
    nirvdrum committed Dec 18, 2014
    Copy the full SHA
    8330db3 View commit details
  3. Copy the full SHA
    6b6e370 View commit details
Original file line number Diff line number Diff line change
@@ -14,6 +14,7 @@
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBignum;

import java.math.BigDecimal;
import java.math.BigInteger;

public class FixnumOrBignumNode extends Node {
@@ -44,7 +45,7 @@ public Object fixnumOrBignum(RubyBignum value) {
}

public Object fixnumOrBignum(RubyContext context, double value) {
if (value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE) {
if (value > Integer.MIN_VALUE && value < Integer.MAX_VALUE) {
// TODO(CS): reusing profiles might not be a good idea
integerProfile.enter();

@@ -53,7 +54,7 @@ public Object fixnumOrBignum(RubyContext context, double value) {

checkLongProfile.enter();

if (value >= Long.MIN_VALUE && value <= Long.MAX_VALUE) {
if (value > Long.MIN_VALUE && value < Long.MAX_VALUE) {
// TODO(CS): reusing profiles might not be a good idea
longProfile.enter();

@@ -62,7 +63,7 @@ public Object fixnumOrBignum(RubyContext context, double value) {

bignumProfile.enter();

return new RubyBignum(context.getCoreLibrary().getBignumClass(), BigInteger.valueOf((long) value));
return new RubyBignum(context.getCoreLibrary().getBignumClass(), new BigDecimal(value).toBigInteger());
}

}
41 changes: 41 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/FloatNodes.java
Original file line number Diff line number Diff line change
@@ -600,6 +600,47 @@ public Object round(double n) {

}

@CoreMethod(names = { "to_i", "to_int", "truncate" })
public abstract static class ToINode extends CoreMethodNode {

@Child protected FixnumOrBignumNode fixnumOrBignum;

private final BranchProfile greaterZero = new BranchProfile();
private final BranchProfile lessZero = new BranchProfile();

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

public ToINode(ToINode prev) {
super(prev);
fixnumOrBignum = prev.fixnumOrBignum;
}

@Specialization
public Object toI(double value) {
if (Double.isInfinite(value)) {
throw new RaiseException(getContext().getCoreLibrary().floatDomainError("Infinity", this));
}

if (Double.isNaN(value)) {
throw new RaiseException(getContext().getCoreLibrary().floatDomainError("NaN", this));
}

double truncated = value;

if (value > 0.0) {
truncated = Math.floor(value);
} else if (value < 0.0) {
truncated = Math.ceil(value);
}

return fixnumOrBignum.fixnumOrBignum(getContext(), truncated);
}

}

@CoreMethod(names = "to_f")
public abstract static class ToFNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -54,6 +54,7 @@ public class CoreLibrary {
@CompilerDirectives.CompilationFinal private RubyClass fileClass;
@CompilerDirectives.CompilationFinal private RubyClass fixnumClass;
@CompilerDirectives.CompilationFinal private RubyClass floatClass;
@CompilerDirectives.CompilationFinal private RubyClass floatDomainErrorClass;
@CompilerDirectives.CompilationFinal private RubyClass hashClass;
@CompilerDirectives.CompilationFinal private RubyClass integerClass;
@CompilerDirectives.CompilationFinal private RubyClass indexErrorClass;
@@ -198,6 +199,7 @@ public void initialize() {
fileClass = new RubyClass(context, objectClass, ioClass, "File");
fixnumClass = new RubyClass(context, objectClass, integerClass, "Fixnum");
floatClass = new RubyClass(context, objectClass, numericClass, "Float");
floatDomainErrorClass = new RubyException.RubyExceptionClass(context, objectClass, rangeErrorClass, "FloatDomainError");
gcModule = new RubyModule(context, objectClass, "GC");
hashClass = new RubyHash.RubyHashClass(context, objectClass);
indexErrorClass = new RubyException.RubyExceptionClass(context, objectClass, standardErrorClass, "IndexError");
@@ -554,6 +556,11 @@ public RubyException syntaxError(String message, Node currentNode) {
return new RubyException(syntaxErrorClass, context.makeString(message), RubyCallStack.getBacktrace(currentNode));
}

public RubyException floatDomainError(String value, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(floatDomainErrorClass, context.makeString(value), RubyCallStack.getBacktrace(currentNode));
}

public RubyException mathDomainError(String method, Node currentNode) {
CompilerAsserts.neverPartOfCompilation();
return new RubyException(edomClass, context.makeString(String.format("Numerical argument is out of domain - \"%s\"", method)), RubyCallStack.getBacktrace(currentNode));
1 change: 0 additions & 1 deletion spec/truffle/tags/core/float/to_i_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/float/to_int_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/float/truncate_tags.txt

This file was deleted.