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

Commits on Jul 17, 2017

  1. Copy the full SHA
    f9fc7de View commit details
  2. move (custom) Float conversion where its used - adjust accordingly

    preparing to be able to handle Java numbers while keeping compat
    kares committed Jul 17, 2017
    Copy the full SHA
    02df77c View commit details
  3. Copy the full SHA
    05a57ec View commit details
  4. Copy the full SHA
    988d421 View commit details
  5. Copy the full SHA
    75860f3 View commit details
  6. Copy the full SHA
    28ffaf0 View commit details
  7. implement coerce for Java numbers; special care for Java's BigDecimal

    we're converting to Ruby but all basic num operations now simply work
    kares committed Jul 17, 2017
    Copy the full SHA
    43e4831 View commit details
31 changes: 22 additions & 9 deletions core/src/main/java/org/jruby/RubyInteger.java
Original file line number Diff line number Diff line change
@@ -41,7 +41,6 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
@@ -54,7 +53,6 @@
import org.jruby.util.StringSupport;

import static org.jruby.RubyEnumerator.enumeratorizeWithSize;
import static org.jruby.util.Numeric.checkInteger;
import static org.jruby.util.Numeric.f_gcd;
import static org.jruby.util.Numeric.f_lcm;
import static org.jruby.RubyEnumerator.SizeFn;
@@ -352,7 +350,7 @@ public RubyString chr(ThreadContext context, IRubyObject arg) {
enc = arg.convertToString().toEncoding(runtime);
}
if (enc == ASCIIEncoding.INSTANCE && value >= 0x80) {
return chr19(context);
return chr(context);
}
return RubyString.newStringNoCopy(runtime, fromEncodedBytes(runtime, enc, value), enc, 0);
}
@@ -505,29 +503,44 @@ public IRubyObject pred(ThreadContext context) {
*/
@JRubyMethod(name = "gcd")
public IRubyObject gcd(ThreadContext context, IRubyObject other) {
checkInteger(context, other);
return f_gcd(context, this, RubyRational.intValue(context, other));
return f_gcd(context, this, RubyInteger.intValue(context, other));
}

/** rb_lcm
*
*/
@JRubyMethod(name = "lcm")
public IRubyObject lcm(ThreadContext context, IRubyObject other) {
checkInteger(context, other);
return f_lcm(context, this, RubyRational.intValue(context, other));
return f_lcm(context, this, RubyInteger.intValue(context, other));
}

/** rb_gcdlcm
*
*/
@JRubyMethod(name = "gcdlcm")
public IRubyObject gcdlcm(ThreadContext context, IRubyObject other) {
checkInteger(context, other);
other = RubyRational.intValue(context, other);
other = RubyInteger.intValue(context, other);
return context.runtime.newArray(f_gcd(context, this, other), f_lcm(context, this, other));
}

static IRubyObject intValue(ThreadContext context, IRubyObject num) {
IRubyObject i;
if (( i = RubyInteger.toInteger(context, num) ) == null) {
throw context.runtime.newTypeError("not an integer");
}
return i;
}

static IRubyObject toInteger(ThreadContext context, IRubyObject num) {
if (num instanceof RubyInteger) return num;
if (num instanceof RubyNumeric && !num.callMethod(context, "integer?").isTrue()) {
return null;
}
if (num instanceof RubyString) return null; // do not want String#to_i
if (num.respondsTo("to_i")) return num.callMethod(context, "to_i");
return null;
}

@Override
@JRubyMethod(name = "numerator")
public IRubyObject numerator(ThreadContext context) {
56 changes: 17 additions & 39 deletions core/src/main/java/org/jruby/RubyNumeric.java
Original file line number Diff line number Diff line change
@@ -201,20 +201,14 @@ public static byte num2chr(IRubyObject arg) {
*
*/
public static long num2long(IRubyObject arg) {
if (arg instanceof RubyFixnum) {
return ((RubyFixnum) arg).getLongValue();
} else {
return other2long(arg);
}
return arg instanceof RubyFixnum ? ((RubyFixnum) arg).getLongValue() : other2long(arg);
}

private static long other2long(IRubyObject arg) throws RaiseException {
if (arg instanceof RubyFloat) return float2long((RubyFloat) arg);
if (arg instanceof RubyBignum) return RubyBignum.big2long((RubyBignum) arg);
if (arg.isNil()) {
throw arg.getRuntime().newTypeError("no implicit conversion from nil to integer");
} else if (arg instanceof RubyFloat) {
return float2long((RubyFloat)arg);
} else if (arg instanceof RubyBignum) {
return RubyBignum.big2long((RubyBignum) arg);
}
return arg.convertToInteger().getLongValue();
}
@@ -246,42 +240,26 @@ public static IRubyObject dbl2num(Ruby runtime, double val) {
*
*/
public static double num2dbl(IRubyObject arg) {
Ruby runtime = arg.getRuntime();

if (arg instanceof RubyBoolean || arg instanceof RubyNil) {
throw runtime.newTypeError("can't convert " + arg.inspect() + " into Float");
}

if (arg instanceof RubyFloat) {
return ((RubyFloat) arg).getDoubleValue();
} else if (arg instanceof RubyBignum) {
if (runtime.getBignum().searchMethod("to_f").isBuiltin()) {
return ((RubyBignum) arg).getDoubleValue();
}
} else if (arg instanceof RubyRational) {
if (runtime.getRational().searchMethod("to_f").isBuiltin()) {
return ((RubyRational) arg).getDoubleValue();
}
}

IRubyObject val = numericToFloat(runtime, arg);
return ((RubyFloat) val).getDoubleValue();
}

private static IRubyObject numericToFloat(Ruby runtime, IRubyObject num) {
if (!(num instanceof RubyNumeric)) {
throw runtime.newTypeError("can't convert " + num.getType() + " into Float");
final Ruby runtime = arg.getRuntime();
if (arg instanceof RubyFixnum && !runtime.isFixnumReopened()) {
return ((RubyFixnum) arg).getDoubleValue();
}

if (num instanceof RubyFloat) {
return num;
if (arg instanceof RubyBignum && runtime.getBignum().searchMethod("to_f").isBuiltin()) {
return ((RubyBignum) arg).getDoubleValue();
}
if (arg instanceof RubyRational && runtime.getRational().searchMethod("to_f").isBuiltin()) {
return ((RubyRational) arg).getDoubleValue();
}

if (num instanceof RubyFixnum && !runtime.isFixnumReopened()) {
return ((RubyFixnum) num).to_f();
if (arg instanceof RubyBoolean || arg instanceof RubyString || arg.isNil()) {
throw runtime.newTypeError("can't convert " + arg.inspect() + " into Float");
}

return TypeConverter.convertToType(num, runtime.getFloat(), "to_f");
IRubyObject val = TypeConverter.convertToType(arg, runtime.getFloat(), "to_f");
return ((RubyFloat) val).getDoubleValue();
}

/** rb_dbl_cmp (numeric.c)
@@ -767,8 +745,8 @@ public final IRubyObject divmod19(ThreadContext context, IRubyObject other) {
/** num_fdiv */
@JRubyMethod(name = "fdiv")
public IRubyObject fdiv(ThreadContext context, IRubyObject other) {
RubyFloat flote = this.convertToFloat();
return sites(context).op_quo.call(context, flote, flote, other);
RubyFloat value = convertToFloat();
return sites(context).op_quo.call(context, value, value, other);
}

/** num_modulo
38 changes: 15 additions & 23 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -25,7 +25,6 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import static org.jruby.util.Numeric.checkInteger;
import static org.jruby.util.Numeric.f_abs;
import static org.jruby.util.Numeric.f_add;
import static org.jruby.util.Numeric.f_cmp;
@@ -68,7 +67,6 @@
import org.jruby.anno.JRubyMethod;
import org.jruby.common.IRubyWarnings;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.ObjectAllocator;
@@ -208,25 +206,15 @@ public static void setCanonicalization(boolean canonical) {
canonicalization = canonical;
}

/** nurat_int_check
*
*/
static void intCheck(ThreadContext context, IRubyObject num) {
if (num instanceof RubyFixnum || num instanceof RubyBignum) return;
if (!(num instanceof RubyNumeric) || !num.callMethod(context, "integer?").isTrue()) {
Ruby runtime = num.getRuntime();
throw runtime.newTypeError("can't convert "
+ num.getMetaClass().getName() + " into Rational");
}
}

/** nurat_int_value
*
*/
static IRubyObject intValue(ThreadContext context, IRubyObject num) {
intCheck(context, num);
if (!(num instanceof RubyInteger)) num = num.callMethod(context, "to_f");
return num;
IRubyObject i;
if (( i = RubyInteger.toInteger(context, num) ) == null) {
throw context.runtime.newTypeError("can't convert " + num.getMetaClass().getName() + " into Rational");
}
return i;
}

/** nurat_s_canonicalize_internal
@@ -590,6 +578,12 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other) {
/** nurat_fdiv
*
*/
// @Override
// @JRubyMethod(name = "fdiv")
// public IRubyObject fdiv(ThreadContext context, IRubyObject other) {
// return f_div(context, f_to_f(context, this), other);
// }

@JRubyMethod(name = "fdiv")
public IRubyObject op_fdiv(ThreadContext context, IRubyObject other) {
return f_div(context, f_to_f(context, this), other);
@@ -808,10 +802,8 @@ public IRubyObject op_abs(ThreadContext context) {
return f_negate(context, this);
}

private IRubyObject op_roundCommonPre(ThreadContext context, IRubyObject n) {
checkInteger(context, n);
Ruby runtime = context.runtime;
return f_expt(context, RubyFixnum.newFixnum(runtime, 10), n);
private static IRubyObject op_roundCommonPre(ThreadContext context, IRubyObject n) {
return f_expt(context, RubyFixnum.newFixnum(context.runtime, 10), intValue(context, n));
}

private IRubyObject op_roundCommonPost(ThreadContext context, IRubyObject s, IRubyObject n, IRubyObject b) {
@@ -1043,8 +1035,8 @@ public IRubyObject marshal_dump(ThreadContext context) {
@JRubyMethod(name = "marshal_load")
public IRubyObject marshal_load(ThreadContext context, IRubyObject arg) {
RubyArray load = arg.convertToArray();
num = load.size() > 0 ? load.eltInternal(0) : context.runtime.getNil();
den = load.size() > 1 ? load.eltInternal(1) : context.runtime.getNil();
num = load.size() > 0 ? load.eltInternal(0) : context.nil;
den = load.size() > 1 ? load.eltInternal(1) : context.nil;

if (f_zero_p(context, den)) {
throw context.runtime.newZeroDivisionError();
65 changes: 65 additions & 0 deletions core/src/main/java/org/jruby/javasupport/ext/JavaLang.java
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyModule;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.javasupport.Java;
import org.jruby.javasupport.JavaClass;
@@ -62,6 +63,7 @@ public static void define(final Ruby runtime) {
Throwable.define(runtime);
Runnable.define(runtime);
Character.define(runtime);
Number.define(runtime);
Class.define(runtime);
ClassLoader.define(runtime);
// Java::byte[].class_eval ...
@@ -307,6 +309,63 @@ protected final IRubyObject doYield(ThreadContext context, Block block, IRubyObj

}

@JRubyClass(name = "Java::JavaLang::Number")
public static class Number {

static RubyClass define(final Ruby runtime) {
final RubyModule Number = Java.getProxyClass(runtime, java.lang.Number.class);
Number.defineAnnotatedMethods(Number.class);
return (RubyClass) Number;
}

@JRubyMethod(name = "to_f")
public static IRubyObject to_f(final ThreadContext context, final IRubyObject self) {
java.lang.Number val = (java.lang.Number) self.toJava(java.lang.Number.class);
return context.runtime.newFloat(val.doubleValue());
}

@JRubyMethod(name = { "to_i", "to_int" })
public static IRubyObject to_i(final ThreadContext context, final IRubyObject self) {
java.lang.Number val = (java.lang.Number) self.toJava(java.lang.Number.class);
if (val instanceof java.math.BigInteger) { // NOTE: should be moved into its own?
return RubyBignum.newBignum(context.runtime, (java.math.BigInteger) val);
}
if (val instanceof java.math.BigDecimal) { // NOTE: should be moved into its own?
return RubyBignum.newBignum(context.runtime, ((java.math.BigDecimal) val).toBigInteger());
}
return context.runtime.newFixnum(val.longValue());
}

@JRubyMethod(name = "integer?")
public static IRubyObject integer_p(final ThreadContext context, final IRubyObject self) {
java.lang.Number val = (java.lang.Number) self.toJava(java.lang.Number.class);
return context.runtime.newBoolean(val instanceof Integer || val instanceof Long ||
val instanceof Short || val instanceof Byte ||
val instanceof java.math.BigInteger);
}

@JRubyMethod(name = "coerce")
public static IRubyObject coerce(final ThreadContext context, final IRubyObject self, final IRubyObject type) {
java.lang.Number val = (java.lang.Number) self.toJava(java.lang.Number.class);

// NOTE: a basic stub that always coverts Java numbers to Ruby ones (for simplicity)
// gist being this is not expected to be used heavily, if so should get special care
final IRubyObject value;
if (val instanceof java.math.BigDecimal) {
final RubyClass klass = context.runtime.getClass("BigDecimal");
if (klass == null) { // user should require 'bigdecimal'
throw context.runtime.newNameError("uninitialized constant BigDecimal", "BigDecimal");
}
value = new RubyBigDecimal(context.runtime, klass, (java.math.BigDecimal) val);
}
else {
value = convertJavaToUsableRubyObject(context.runtime, val);
}
return context.runtime.newArray(type, value);
}

}

@JRubyClass(name = "Java::JavaLang::Character")
public static class Character {

@@ -330,6 +389,12 @@ private static char to_char(final IRubyObject num) {
return (java.lang.Character) num.toJava(java.lang.Character.TYPE);
}

@JRubyMethod(name = "to_i")
public static IRubyObject to_i(final ThreadContext context, final IRubyObject self) {
java.lang.Character c = (java.lang.Character) self.toJava(java.lang.Character.class);
return context.runtime.newFixnum(c);
}

}

@JRubyClass(name = "Java::JavaLang::Class")
25 changes: 17 additions & 8 deletions core/src/main/java/org/jruby/util/Pack.java
Original file line number Diff line number Diff line change
@@ -83,23 +83,32 @@ public class Pack {
private static final Converter[] converters = new Converter[256];

private static long num2quad(IRubyObject arg) {
if (arg == arg.getRuntime().getNil()) {
return 0L;
}
else if (arg instanceof RubyBignum) {
BigInteger big = ((RubyBignum)arg).getValue();
if (arg.isNil()) return 0L;
if (arg instanceof RubyBignum) {
BigInteger big = ((RubyBignum) arg).getValue();
return big.longValue();
}
return RubyNumeric.num2long(arg);
}

private static float obj2flt(Ruby runtime, IRubyObject o) {
return (float) TypeConverter.toFloat(runtime, o).getDoubleValue();
return (float) toFloat(runtime, o).getDoubleValue();
}

private static double obj2dbl(Ruby runtime, IRubyObject o) {
return TypeConverter.toFloat(runtime, o).getDoubleValue();
}
return toFloat(runtime, o).getDoubleValue();
}

// MRI: rb_to_float 1.9
private static RubyFloat toFloat(Ruby runtime, IRubyObject obj) {
if (obj instanceof RubyNumeric) {
return ((RubyNumeric) obj).convertToFloat();
}
if (obj instanceof RubyString || obj.isNil()) {
throw runtime.newTypeError(obj, "Float");
}
return (RubyFloat) TypeConverter.convertToType(obj, runtime.getFloat(), "to_f", true);
}

static {
uu_table =
Loading