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

Commits on Dec 18, 2015

  1. Copy the full SHA
    e56675c View commit details
  2. Copy the full SHA
    824d351 View commit details
  3. Copy the full SHA
    a7265c6 View commit details
  4. Copy the full SHA
    aeea008 View commit details
Showing with 248 additions and 282 deletions.
  1. +133 −156 core/src/main/java/org/jruby/RubyFixnum.java
  2. +115 −126 core/src/main/java/org/jruby/RubyFloat.java
289 changes: 133 additions & 156 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
* Copyright (C) 2005 David Corbin <dcorbin@users.sourceforge.net>
* Copyright (C) 2006 Antti Karanta <antti.karanta@napa.fi>
* Copyright (C) 2007 Miguel Covarrubias <mlcovarrubias@gmail.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -36,12 +36,13 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import java.math.BigInteger;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ObjectAllocator;
@@ -53,37 +54,32 @@
import org.jruby.util.ByteList;
import org.jruby.util.ConvertBytes;
import org.jruby.util.Numeric;
import org.jruby.util.TypeCoercer;

import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

/**
/**
* Implementation of the Fixnum class.
*/
@JRubyClass(name="Fixnum", parent="Integer", include="Precision")
public class RubyFixnum extends RubyInteger implements Constantizable {

public static RubyClass createFixnumClass(Ruby runtime) {
RubyClass fixnum = runtime.defineClass("Fixnum", runtime.getInteger(),
ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
runtime.setFixnum(fixnum);

fixnum.setClassIndex(ClassIndex.FIXNUM);
fixnum.setReifiedClass(RubyFixnum.class);

fixnum.kindOf = new RubyModule.JavaClassKindOf(RubyFixnum.class);

fixnum.defineAnnotatedMethods(RubyFixnum.class);

for (int i = 0; i < runtime.fixnumCache.length; i++) {
runtime.fixnumCache[i] = new RubyFixnum(fixnum, i - CACHE_OFFSET);
}

return fixnum;
}

private final long value;
private static final int BIT_SIZE = 64;
public static final long SIGN_BIT = (1L << (BIT_SIZE - 1));
@@ -99,7 +95,7 @@ private static IRubyObject fixCoerce(IRubyObject x) {
} while (!(x instanceof RubyFixnum) && !(x instanceof RubyBignum));
return x;
}

private IRubyObject bitCoerce(ThreadContext context, IRubyObject y) {
if(!(y instanceof RubyFixnum || y instanceof RubyBignum)) {
RubyArray ary = doCoerce(context, y, true);
@@ -110,7 +106,7 @@ private IRubyObject bitCoerce(ThreadContext context, IRubyObject y) {
}
return y;
}

public RubyFixnum(Ruby runtime) {
this(runtime, 0);
}
@@ -120,13 +116,13 @@ public RubyFixnum(Ruby runtime, long value) {
this.value = value;
this.flags |= FROZEN_F;
}

private RubyFixnum(RubyClass klazz, long value) {
super(klazz);
this.value = value;
this.flags |= FROZEN_F;
}

@Override
public ClassIndex getNativeClassIndex() {
return ClassIndex.FIXNUM;
@@ -152,8 +148,8 @@ public Object constant() {

return constant;
}
/**

/**
* short circuit for Fixnum key comparison
*/
@Override
@@ -170,12 +166,12 @@ public IRubyObject equal_p(ThreadContext context, IRubyObject obj) {
public IRubyObject equal_p19(ThreadContext context, IRubyObject obj) {
return context.runtime.newBoolean(this == obj || eql(obj));
}

@Override
public boolean isImmediate() {
return true;
}

@Override
public RubyClass getSingletonClass() {
throw getRuntime().newTypeError("can't define singleton");
@@ -197,7 +193,7 @@ public long getLongValue() {
}

@Override
public int getIntValue() { return (int)value; }
public int getIntValue() { return (int) value; }

@Override
public BigInteger getBigIntegerValue() {
@@ -210,7 +206,7 @@ public static RubyFixnum newFixnum(Ruby runtime, long value) {
}
return new RubyFixnum(runtime, value);
}

private static boolean isInCacheRange(long value) {
return value <= CACHE_OFFSET - 1 && value >= -CACHE_OFFSET;
}
@@ -226,19 +222,19 @@ public static RubyFixnum zero(Ruby runtime) {
public static RubyFixnum one(Ruby runtime) {
return runtime.fixnumCache[CACHE_OFFSET + 1];
}

public static RubyFixnum two(Ruby runtime) {
return runtime.fixnumCache[CACHE_OFFSET + 2];
}

public static RubyFixnum three(Ruby runtime) {
return runtime.fixnumCache[CACHE_OFFSET + 3];
}

public static RubyFixnum four(Ruby runtime) {
return runtime.fixnumCache[CACHE_OFFSET + 4];
}

public static RubyFixnum five(Ruby runtime) {
return runtime.fixnumCache[CACHE_OFFSET + 5];
}
@@ -254,75 +250,74 @@ public RubyFixnum hash() {

@Override
public final int hashCode() {
return (int)(value ^ value >>> 32);
return (int) (value ^ value >>> 32);
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof RubyFixnum) {

if (other instanceof RubyFixnum) {
RubyFixnum num = (RubyFixnum)other;

if (num.value == value) {
return true;
}
} else if (other instanceof RubyFloat) {
return (double)value == ((RubyFloat) other).getDoubleValue();
}

return false;
}

/* ================
* Instance Methods
* ================
* ================
*/
@Override
@JRubyMethod
public IRubyObject times(ThreadContext context, Block block) {
if (block.isGiven()) {
Ruby runtime = context.runtime;
long lvalue = this.value;
final long value = this.value;
boolean checkArity = block.type.checkArity;

if (block.getSignature() == Signature.NO_ARGUMENTS) {
if (checkArity) {
// must pass arg
IRubyObject nil = runtime.getNil();
for (long i = 0; i < lvalue; i++) {
final IRubyObject nil = context.nil;
for (long i = 0; i < value; i++) {
block.yieldSpecific(context, nil);
}
} else {
// no arg needed
for (long i = 0; i < lvalue; i++) {
for (long i = 0; i < value; i++) {
block.yieldSpecific(context);
}
}
} else {
for (long i = 0; i < lvalue; i++) {
final Ruby runtime = context.runtime;
for (long i = 0; i < value; i++) {
block.yield(context, RubyFixnum.newFixnum(runtime, i));
}
}
return this;
} else {
return RubyEnumerator.enumeratorizeWithSize(context, this, "times", timesSizeFn(context.runtime));
}
return RubyEnumerator.enumeratorizeWithSize(context, this, "times", timesSizeFn(context.runtime));
}

/** fix_to_s
*
*
*/
public RubyString to_s(IRubyObject[] args) {
switch (args.length) {
case 0: return to_s();
case 1: return to_s(args[0]);
default: throw getRuntime().newArgumentError(args.length, 1);
case 0: return to_s();
case 1: return to_s(args[0]);
default: throw getRuntime().newArgumentError(args.length, 1);
}
}

@JRubyMethod
@Override
public RubyString to_s() {
@@ -331,7 +326,7 @@ public RubyString to_s() {
str.setEncoding(USASCIIEncoding.INSTANCE);
return str;
}

@JRubyMethod
public RubyString to_s(IRubyObject arg0) {
int base = num2int(arg0);
@@ -344,17 +339,17 @@ public RubyString to_s(IRubyObject arg0) {
}

/** fix_to_sym
*
*
*/
@Deprecated
public IRubyObject to_sym() {
RubySymbol symbol = RubySymbol.getSymbolLong(getRuntime(), value);
return symbol != null ? symbol : getRuntime().getNil();

return symbol != null ? symbol : getRuntime().getNil();
}

/** fix_uminus
*
*
*/
@JRubyMethod(name = "-@")
public IRubyObject op_uminus() {
@@ -365,32 +360,32 @@ public IRubyObject op_uminus() {
}

/** fix_plus
*
*
*/
@JRubyMethod(name = "+")
public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) {
return addFixnum(context, (RubyFixnum)other);
return addFixnum(context, (RubyFixnum) other);
}
return addOther(context, other);
}

public IRubyObject op_plus(ThreadContext context, long otherValue) {
long result = value + otherValue;
if (Helpers.additionOverflowed(value, otherValue, result)) {
return addAsBignum(context, otherValue);
}
return newFixnum(context.runtime, result);
}

public IRubyObject op_plus_one(ThreadContext context) {
long result = value + 1;
if (result == Long.MIN_VALUE) {
return addAsBignum(context, 1);
}
return newFixnum(context.runtime, result);
}

public IRubyObject op_plus_two(ThreadContext context) {
long result = value + 2;
//- if (result == Long.MIN_VALUE + 1) { //-code
@@ -399,7 +394,7 @@ public IRubyObject op_plus_two(ThreadContext context) {
}
return newFixnum(context.runtime, result);
}

private IRubyObject addFixnum(ThreadContext context, RubyFixnum other) {
long otherValue = other.value;
long result = value + otherValue;
@@ -416,7 +411,7 @@ private IRubyObject addAsBignum(ThreadContext context, RubyFixnum other) {
private IRubyObject addAsBignum(ThreadContext context, long other) {
return RubyBignum.newBignum(context.runtime, value).op_plus(context, other);
}

private IRubyObject addOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyBignum) {
return ((RubyBignum) other).op_plus(context, this);
@@ -428,7 +423,7 @@ private IRubyObject addOther(ThreadContext context, IRubyObject other) {
}

/** fix_minus
*
*
*/
@JRubyMethod(name = "-")
public IRubyObject op_minus(ThreadContext context, IRubyObject other) {
@@ -471,15 +466,15 @@ private IRubyObject subtractFixnum(ThreadContext context, RubyFixnum other) {
}
return newFixnum(context.runtime, result);
}

private IRubyObject subtractAsBignum(ThreadContext context, RubyFixnum other) {
return RubyBignum.newBignum(context.runtime, value).op_minus(context, other);
}

private IRubyObject subtractAsBignum(ThreadContext context, long other) {
return RubyBignum.newBignum(context.runtime, value).op_minus(context, other);
}

private IRubyObject subtractOther(ThreadContext context, IRubyObject other) {
if (other instanceof RubyBignum) {
return RubyBignum.newBignum(context.runtime, value).op_minus(context, other);
@@ -490,7 +485,7 @@ private IRubyObject subtractOther(ThreadContext context, IRubyObject other) {
}

/** fix_mul
*
*
*/
@JRubyMethod(name = "*")
public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
@@ -517,16 +512,16 @@ public IRubyObject op_mul(ThreadContext context, long otherValue) {
// value == -1; otherValue == Long.MIN_VALUE;
// result = value * othervalue; #=> Long.MIN_VALUE (overflow)
// result / value #=> Long.MIN_VALUE (overflow) == otherValue
Ruby runtime = context.runtime;
long value = this.value;

final Ruby runtime = context.runtime;
final long value = this.value;

// fast check for known ranges that won't overflow
if (value <= 3037000499L && otherValue <= 3037000499L &&
value >= -3037000499L && otherValue >= -3037000499L) {
return newFixnum(runtime, value * otherValue);
}

if (value == 0 || otherValue == 0) {
return RubyFixnum.zero(runtime);
}
@@ -548,10 +543,10 @@ public IRubyObject op_mul(ThreadContext context, long otherValue) {
* here is terrible MRI gotcha:
* 1.div 3.0 -> 0
* 1 / 3.0 -> 0.3333333333333333
*
*
* MRI is also able to do it in one place by looking at current frame in rb_num_coerce_bin:
* rb_funcall(x, ruby_frame->orig_func, 1, y);
*
*
* also note that RubyFloat doesn't override Numeric.div
*/
@JRubyMethod(name = "div")
@@ -560,7 +555,7 @@ public IRubyObject div_div(ThreadContext context, IRubyObject other) {

return idiv(context, other, "div");
}

@JRubyMethod(name = "/")
public IRubyObject op_div(ThreadContext context, IRubyObject other) {
return idiv(context, other, "/");
@@ -593,7 +588,7 @@ public IRubyObject pred(ThreadContext context) {
public IRubyObject idiv(ThreadContext context, IRubyObject other, String method) {
if (other instanceof RubyFixnum) {
return idivLong(context, value, ((RubyFixnum) other).value);
}
}
return coerceBin(context, method, other);
}

@@ -604,7 +599,7 @@ public IRubyObject idiv(ThreadContext context, long y, String method) {
}

private IRubyObject idivLong(ThreadContext context, long x, long y) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
if (y == 0) {
throw runtime.newZeroDivisionError();
}
@@ -627,9 +622,9 @@ private IRubyObject idivLong(ThreadContext context, long x, long y) {
}
return runtime.newFixnum(result);
}

/** fix_mod
*
*
*/
@JRubyMethod(name = {"%", "modulo"})
public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
@@ -639,7 +634,7 @@ public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
}
return coerceBin(context, "%", other);
}

public IRubyObject op_mod(ThreadContext context, long other) {
return moduloFixnum(context, other);
}
@@ -661,30 +656,30 @@ private IRubyObject moduloFixnum(ThreadContext context, long other) {
}
return context.runtime.newFixnum(mod);
}

/** fix_divmod
*
*
*/
@JRubyMethod(name = "divmod")
@Override
public IRubyObject divmod(ThreadContext context, IRubyObject other) {
checkZeroDivisionError(context, other);
if (other instanceof RubyFixnum) {
return divmodFixnum(context, other);
return divmodFixnum(context, (RubyFixnum) other);
}
return coerceBin(context, "divmod", other);
}

private IRubyObject divmodFixnum(ThreadContext context, IRubyObject other) {
long x = value;
long y = ((RubyFixnum) other).value;
private IRubyObject divmodFixnum(ThreadContext context, RubyFixnum other) {
final Ruby runtime = context.runtime;

final long x = this.value;
final long y = other.value;
if (y == 0) {
throw runtime.newZeroDivisionError();
}

long mod;
IRubyObject integerDiv;
long mod; final RubyInteger integerDiv;
if (y == -1) {
if (x == MIN) {
integerDiv = RubyBignum.newBignum(runtime, BigInteger.valueOf(x).negate());
@@ -706,23 +701,24 @@ private IRubyObject divmodFixnum(ThreadContext context, IRubyObject other) {
IRubyObject fixMod = RubyFixnum.newFixnum(runtime, mod);
return RubyArray.newArray(runtime, integerDiv, fixMod);
}

/** fix_quo
*
*
*/
@Deprecated
@Override
public IRubyObject quo(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum) {
return RubyFloat.newFloat(context.runtime, (double) value / (double) ((RubyFixnum) other).value);
} else if (other instanceof RubyBignum) {
return RubyFloat.newFloat(context.runtime, (double) value / (double) ((RubyBignum) other).getDoubleValue());
}
if (other instanceof RubyBignum) {
return RubyFloat.newFloat(context.runtime, (double) value / ((RubyBignum) other).getDoubleValue());
}
return coerceBin(context, "quo", other);
}

/** fix_pow
*
/** fix_pow
*
*/
@JRubyMethod(name = "**")
public IRubyObject op_pow(ThreadContext context, IRubyObject other) {
@@ -761,7 +757,7 @@ public IRubyObject op_pow_19(ThreadContext context, IRubyObject other) {
if (other instanceof RubyNumeric) {
double d_other = ((RubyNumeric) other).getDoubleValue();
if (value < 0 && (d_other != Math.round(d_other))) {
return RubyComplex.newComplexRaw(getRuntime(), this).callMethod(context, "**", other);
return RubyComplex.newComplexRaw(context.runtime, this).callMethod(context, "**", other);
}
if (other instanceof RubyFixnum) {
return powerFixnum19(context, other);
@@ -818,7 +814,7 @@ private IRubyObject powerFixnum19(ThreadContext context, IRubyObject other) {
}

/** fix_abs
*
*
*/
@JRubyMethod
@Override
@@ -835,7 +831,7 @@ public IRubyObject abs(ThreadContext context) {
}

/** fix_abs/1.9
*
*
*/
@JRubyMethod(name = "magnitude")
@Override
@@ -844,7 +840,7 @@ public IRubyObject magnitude(ThreadContext context) {
}

/** fix_equal
*
*
*/
@JRubyMethod(name = "==")
@Override
@@ -880,19 +876,19 @@ private IRubyObject op_equalOther(ThreadContext context, IRubyObject other) {
public final int compareTo(IRubyObject other) {
if (other instanceof RubyFixnum) {
long otherValue = ((RubyFixnum)other).value;
return value == otherValue ? 0 : value > otherValue ? 1 : -1;
return value == otherValue ? 0 : value > otherValue ? 1 : -1;
}
return compareToOther(other);
}

private int compareToOther(IRubyObject other) {
if (other instanceof RubyBignum) return BigInteger.valueOf(value).compareTo(((RubyBignum)other).getValue());
if (other instanceof RubyFloat) return Double.compare((double)value, ((RubyFloat)other).getDoubleValue());
return (int)coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
return (int) coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
}

/** fix_cmp
*
*
*/
@JRubyMethod(name = "<=>")
public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
@@ -917,7 +913,7 @@ private IRubyObject compareOther(ThreadContext context, IRubyObject other) {
}

/** fix_gt
*
*
*/
@JRubyMethod(name = ">")
public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
@@ -948,7 +944,7 @@ private IRubyObject op_gtOther(ThreadContext context, IRubyObject other) {
}

/** fix_ge
*
*
*/
@JRubyMethod(name = ">=")
public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
@@ -978,7 +974,7 @@ private IRubyObject op_geOther(ThreadContext context, IRubyObject other) {
}

/** fix_lt
*
*
*/
@JRubyMethod(name = "<")
public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
@@ -1008,7 +1004,7 @@ private IRubyObject op_ltOther(ThreadContext context, IRubyObject other) {
}

/** fix_le
*
*
*/
@JRubyMethod(name = "<=")
public IRubyObject op_le(ThreadContext context, IRubyObject other) {
@@ -1038,15 +1034,15 @@ private IRubyObject op_leOther(ThreadContext context, IRubyObject other) {
}

/** fix_rev
*
*
*/
@JRubyMethod(name = "~")
public IRubyObject op_neg() {
return newFixnum(~value);
}

/** fix_and
*
*
*/
@JRubyMethod(name = "&")
public IRubyObject op_and(ThreadContext context, IRubyObject other) {
@@ -1059,7 +1055,7 @@ private IRubyObject op_andOther(ThreadContext context, IRubyObject other) {
}
return ((RubyBignum) other).op_and(context, this);
}

public IRubyObject op_and(ThreadContext context, long other) {
return newFixnum(context.runtime, value & other);
}
@@ -1071,9 +1067,9 @@ private IRubyObject op_and19(ThreadContext context, IRubyObject other) {

return op_andOther(context, other);
}
/** fix_or
*

/** fix_or
*
*/
@JRubyMethod(name = "|")
public IRubyObject op_or(ThreadContext context, IRubyObject other) {
@@ -1088,8 +1084,8 @@ public IRubyObject op_or(ThreadContext context, long other) {
return newFixnum(context.runtime, value | other);
}

/** fix_xor
*
/** fix_xor
*
*/
@JRubyMethod(name = "^")
public IRubyObject op_xor(ThreadContext context, IRubyObject other) {
@@ -1100,9 +1096,9 @@ private IRubyObject op_xor18(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFixnum || (other = fixCoerce(other)) instanceof RubyFixnum) {
return newFixnum(context.runtime, value ^ ((RubyFixnum) other).value);
}
return ((RubyBignum) other).op_xor(context, this);
return ((RubyBignum) other).op_xor(context, this);
}

public IRubyObject op_xor(ThreadContext context, long other) {
return newFixnum(context.runtime, value ^ other);
}
@@ -1113,9 +1109,9 @@ private IRubyObject op_xor19(ThreadContext context, IRubyObject other) {
}
return op_xor18(context, other);
}
/** fix_aref
*

/** fix_aref
*
*/
@JRubyMethod(name = "[]")
public IRubyObject op_aref(IRubyObject other) {
@@ -1138,68 +1134,68 @@ public IRubyObject op_aref(IRubyObject other) {
return (value & (1L << otherValue)) == 0 ? RubyFixnum.zero(getRuntime()) : RubyFixnum.one(getRuntime());
}

/** fix_lshift
*
/** fix_lshift
*
*/
@JRubyMethod(name = "<<")
public IRubyObject op_lshift(IRubyObject other) {
if (!(other instanceof RubyFixnum)) return RubyBignum.newBignum(getRuntime(), value).op_lshift(other);

return op_lshift(((RubyFixnum)other).getLongValue());
}

public IRubyObject op_lshift(long width) {
return width < 0 ? rshift(-width) : lshift(width);
return width < 0 ? rshift(-width) : lshift(width);
}

private IRubyObject lshift(long width) {
if (width > BIT_SIZE - 1 || ((~0L << BIT_SIZE - width - 1) & value) != 0) {
return RubyBignum.newBignum(getRuntime(), value).op_lshift(RubyFixnum.newFixnum(getRuntime(), width));
}
return RubyFixnum.newFixnum(getRuntime(), value << width);
}

/** fix_rshift
*
/** fix_rshift
*
*/
@JRubyMethod(name = ">>")
public IRubyObject op_rshift(IRubyObject other) {
if (!(other instanceof RubyFixnum)) return RubyBignum.newBignum(getRuntime(), value).op_rshift(other);

return op_rshift(((RubyFixnum)other).getLongValue());
}

public IRubyObject op_rshift(long width) {
if (width == 0) return this;

return width < 0 ? lshift(-width) : rshift(width);
return width < 0 ? lshift(-width) : rshift(width);
}
private IRubyObject rshift(long width) {

private IRubyObject rshift(long width) {
if (width >= BIT_SIZE - 1) {
return value < 0 ? RubyFixnum.minus_one(getRuntime()) : RubyFixnum.zero(getRuntime());
return value < 0 ? RubyFixnum.minus_one(getRuntime()) : RubyFixnum.zero(getRuntime());
}
return RubyFixnum.newFixnum(getRuntime(), value >> width);
}

/** fix_to_f
*
/** fix_to_f
*
*/
@JRubyMethod
public IRubyObject to_f() {
return RubyFloat.newFloat(getRuntime(), (double) value);
}

/** fix_size
*
/** fix_size
*
*/
@JRubyMethod
public IRubyObject size() {
return newFixnum((long) ((BIT_SIZE + 7) / 8));
}

/** fix_zero_p
*
/** fix_zero_p
*
*/
@JRubyMethod(name = "zero?")
public IRubyObject zero_p() {
@@ -1221,7 +1217,7 @@ public IRubyObject id() {
if (value <= Long.MAX_VALUE / 2 && value >= Long.MIN_VALUE / 2) {
return newFixnum(2 * value + 1);
}

return super.id();
}

@@ -1233,8 +1229,7 @@ public IRubyObject taint(ThreadContext context) {
// Piece of mri rb_to_id
@Override
public String asJavaString() {
Ruby runtime = getRuntime();
throw runtime.newTypeError(inspect().toString() + " is not a symbol");
throw getRuntime().newTypeError(inspect().toString() + " is not a symbol");
}

public static RubyFixnum unmarshalFrom(UnmarshalStream input) throws java.io.IOException {
@@ -1243,37 +1238,19 @@ public static RubyFixnum unmarshalFrom(UnmarshalStream input) throws java.io.IOE

/* ================
* Singleton Methods
* ================
* ================
*/

/** rb_fix_induced_from
*
*
*/
@Deprecated
public static IRubyObject induced_from(IRubyObject recv, IRubyObject other) {
return RubyNumeric.num2fix(other);
}

private static final Map<Class, TypeCoercer> JAVA_COERCERS = new HashMap<Class, TypeCoercer>();

static {
TypeCoercer intCoercer = new TypeCoercer() {
public Object coerce(IRubyObject self) {
RubyFixnum fixnum = (RubyFixnum)self;

if (fixnum.value > Integer.MAX_VALUE) {
throw self.getRuntime().newRangeError("Fixnum " + fixnum.value + " is too large for Java int");
}

return Integer.valueOf((int)fixnum.value);
}
};
JAVA_COERCERS.put(int.class, intCoercer);
JAVA_COERCERS.put(Integer.class, intCoercer);
}

private void checkZeroDivisionError(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat && ((RubyFloat)other).getDoubleValue() == 0.0d) {
if (other instanceof RubyFloat && ((RubyFloat) other).getDoubleValue() == 0.0d) {
throw context.runtime.newZeroDivisionError();
}
}
241 changes: 115 additions & 126 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@
* Copyright (C) 2004 Charles O Nutter <headius@headius.com>
* Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
* Copyright (C) 2008 Joseph LaFata <joe@quibb.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -39,24 +39,7 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import static org.jruby.util.Numeric.f_abs;
import static org.jruby.util.Numeric.f_add;
import static org.jruby.util.Numeric.f_expt;
import static org.jruby.util.Numeric.f_lshift;
import static org.jruby.util.Numeric.f_mul;
import static org.jruby.util.Numeric.f_negate;
import static org.jruby.util.Numeric.f_negative_p;
import static org.jruby.util.Numeric.f_sub;
import static org.jruby.util.Numeric.f_to_r;
import static org.jruby.util.Numeric.f_zero_p;
import static org.jruby.util.Numeric.frexp;
import static org.jruby.util.Numeric.ldexp;
import static org.jruby.util.Numeric.nurat_rationalize_internal;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.lang.Math;

import org.jcodings.specific.ASCIIEncoding;
import org.jcodings.specific.USASCIIEncoding;
@@ -74,6 +57,19 @@

import static org.jruby.runtime.Helpers.invokedynamic;
import static org.jruby.runtime.invokedynamic.MethodNames.OP_EQUAL;
import static org.jruby.util.Numeric.f_abs;
import static org.jruby.util.Numeric.f_add;
import static org.jruby.util.Numeric.f_expt;
import static org.jruby.util.Numeric.f_lshift;
import static org.jruby.util.Numeric.f_mul;
import static org.jruby.util.Numeric.f_negate;
import static org.jruby.util.Numeric.f_negative_p;
import static org.jruby.util.Numeric.f_sub;
import static org.jruby.util.Numeric.f_to_r;
import static org.jruby.util.Numeric.f_zero_p;
import static org.jruby.util.Numeric.frexp;
import static org.jruby.util.Numeric.ldexp;
import static org.jruby.util.Numeric.nurat_rationalize_internal;

/**
* A representation of a float object
@@ -98,19 +94,19 @@ public static RubyClass createFloatClass(Ruby runtime) {

floatc.setClassIndex(ClassIndex.FLOAT);
floatc.setReifiedClass(RubyFloat.class);

floatc.kindOf = new RubyModule.JavaClassKindOf(RubyFloat.class);

floatc.getSingletonClass().undefineMethod("new");

// Java Doubles are 64 bit long:
// Java Doubles are 64 bit long:
floatc.defineConstant("ROUNDS", RubyFixnum.newFixnum(runtime, ROUNDS));
floatc.defineConstant("RADIX", RubyFixnum.newFixnum(runtime, RADIX));
floatc.defineConstant("MANT_DIG", RubyFixnum.newFixnum(runtime, MANT_DIG));
floatc.defineConstant("DIG", RubyFixnum.newFixnum(runtime, DIG));
// Double.MAX_EXPONENT since Java 1.6
floatc.defineConstant("MIN_EXP", RubyFixnum.newFixnum(runtime, MIN_EXP));
// Double.MAX_EXPONENT since Java 1.6
// Double.MAX_EXPONENT since Java 1.6
floatc.defineConstant("MAX_EXP", RubyFixnum.newFixnum(runtime, MAX_EXP));
floatc.defineConstant("MIN_10_EXP", RubyFixnum.newFixnum(runtime, MIN_10_EXP));
floatc.defineConstant("MAX_10_EXP", RubyFixnum.newFixnum(runtime, MAX_10_EXP));
@@ -127,7 +123,7 @@ public static RubyClass createFloatClass(Ruby runtime) {
}

private final double value;

@Override
public ClassIndex getNativeClassIndex() {
return ClassIndex.FLOAT;
@@ -179,7 +175,7 @@ public int getIntValue() {
public BigInteger getBigIntegerValue() {
return BigInteger.valueOf((long)value);
}

@Override
public RubyFloat convertToFloat() {
return this;
@@ -196,11 +192,11 @@ public static RubyFloat newFloat(Ruby runtime, double value) {

/* ================
* Instance Methods
* ================
* ================
*/

/** rb_flo_induced_from
*
*
*/
@Deprecated
public static IRubyObject induced_from(ThreadContext context, IRubyObject recv, IRubyObject number) {
@@ -209,22 +205,22 @@ public static IRubyObject induced_from(ThreadContext context, IRubyObject recv,
} else if (number instanceof RubyFloat) {
return number;
}
throw recv.getRuntime().newTypeError(
"failed to convert " + number.getMetaClass() + " into Float");
throw recv.getRuntime().newTypeError("failed to convert " + number.getMetaClass() + " into Float");
}

private final static DecimalFormat FORMAT = new DecimalFormat("##############0.0##############",
new DecimalFormatSymbols(Locale.ENGLISH));

/** flo_to_s
*
*
*/
@JRubyMethod(name = "to_s")
@Override
public IRubyObject to_s() {
Ruby runtime = getRuntime();
if (Double.isInfinite(value)) return RubyString.newString(runtime, value < 0 ? "-Infinity" : "Infinity");
if (Double.isNaN(value)) return RubyString.newString(runtime, "NaN");
final Ruby runtime = getRuntime();
if (Double.isInfinite(value)) {
return RubyString.newString(runtime, value < 0 ? "-Infinity" : "Infinity");
}
if (Double.isNaN(value)) {
return RubyString.newString(runtime, "NaN");
}

ByteList buf = new ByteList();
// Under 1.9, use full-precision float formatting (JRUBY-4846).
@@ -233,7 +229,7 @@ public IRubyObject to_s() {
Sprintf.sprintf(buf, Locale.US, "%#.20g", this);
int e = buf.indexOf('e');
if (e == -1) e = buf.getRealSize();
ASCIIEncoding ascii = ASCIIEncoding.INSTANCE;
ASCIIEncoding ascii = ASCIIEncoding.INSTANCE;

if (!ascii.isDigit(buf.get(e - 1))) {
buf.setRealSize(0);
@@ -253,7 +249,7 @@ public IRubyObject to_s() {
}

/** flo_coerce
*
*
*/
@JRubyMethod(name = "coerce", required = 1)
@Override
@@ -262,15 +258,15 @@ public IRubyObject coerce(IRubyObject other) {
}

/** flo_uminus
*
*
*/
@JRubyMethod(name = "-@")
public IRubyObject op_uminus() {
return RubyFloat.newFloat(getRuntime(), -value);
}

/** flo_plus
*
*
*/
@JRubyMethod(name = "+", required = 1)
public IRubyObject op_plus(ThreadContext context, IRubyObject other) {
@@ -289,7 +285,7 @@ public IRubyObject op_plus(ThreadContext context, double other) {
}

/** flo_minus
*
*
*/
@JRubyMethod(name = "-", required = 1)
public IRubyObject op_minus(ThreadContext context, IRubyObject other) {
@@ -308,7 +304,7 @@ public IRubyObject op_minus(ThreadContext context, double other) {
}

/** flo_mul
*
*
*/
@JRubyMethod(name = "*", required = 1)
public IRubyObject op_mul(ThreadContext context, IRubyObject other) {
@@ -327,9 +323,9 @@ public IRubyObject op_mul(ThreadContext context, double other) {
return RubyFloat.newFloat(
getRuntime(), value * other);
}

/** flo_div
*
*
*/
@JRubyMethod(name = "/", required = 1)
public IRubyObject op_fdiv(ThreadContext context, IRubyObject other) { // don't override Numeric#div !
@@ -356,7 +352,7 @@ public IRubyObject magnitude(ThreadContext context, IRubyObject other) {
}

/** flo_mod
*
*
*/
public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
switch (other.getMetaClass().getClassIndex()) {
@@ -383,7 +379,7 @@ public IRubyObject op_mod(ThreadContext context, double other) {
}

/** flo_mod
*
*
*/
@JRubyMethod(name = {"%", "modulo"}, required = 1)
public IRubyObject op_mod19(ThreadContext context, IRubyObject other) {
@@ -395,7 +391,7 @@ public IRubyObject op_mod19(ThreadContext context, IRubyObject other) {
}

/** flo_divmod
*
*
*/
@Override
public IRubyObject divmod(ThreadContext context, IRubyObject other) {
@@ -424,9 +420,9 @@ public IRubyObject divmod(ThreadContext context, IRubyObject other) {
return coerceBin(context, "divmod", other);
}
}

/** flo_divmod
*
*
*/
@JRubyMethod(name = "divmod", required = 1)
public IRubyObject divmod19(ThreadContext context, IRubyObject other) {
@@ -436,26 +432,26 @@ public IRubyObject divmod19(ThreadContext context, IRubyObject other) {
}
return divmod(context, other);
}

/** flo_pow
*
*
*/
public IRubyObject op_pow(ThreadContext context, IRubyObject other) {
switch (other.getMetaClass().getClassIndex()) {
case FIXNUM:
case BIGNUM:
case FLOAT:
return RubyFloat.newFloat(getRuntime(), Math.pow(value, ((RubyNumeric) other)
return RubyFloat.newFloat(context.runtime, Math.pow(value, ((RubyNumeric) other)
.getDoubleValue()));
default:
return coerceBin(context, "**", other);
}
}

public IRubyObject op_pow(ThreadContext context, double other) {
return RubyFloat.newFloat(getRuntime(), Math.pow(value, other));
return RubyFloat.newFloat(context.runtime, Math.pow(value, other));
}

@JRubyMethod(name = "**", required = 1)
public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
switch (other.getMetaClass().getClassIndex()) {
@@ -464,7 +460,7 @@ public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
case FLOAT:
double d_other = ((RubyNumeric) other).getDoubleValue();
if (value < 0 && (d_other != Math.round(d_other))) {
return RubyComplex.newComplexRaw(getRuntime(), this).callMethod(context, "**", other);
return RubyComplex.newComplexRaw(context.runtime, this).callMethod(context, "**", other);
} else {
return op_pow(context, other);
}
@@ -474,38 +470,37 @@ public IRubyObject op_pow19(ThreadContext context, IRubyObject other) {
}

/** flo_eq
*
*
*/
@JRubyMethod(name = "==", required = 1)
@Override
public IRubyObject op_equal(ThreadContext context, IRubyObject other) {
if (Double.isNaN(value)) {
return getRuntime().getFalse();
return context.runtime.getFalse();
}
switch (other.getMetaClass().getClassIndex()) {
case FIXNUM:
case BIGNUM:
case FLOAT:
return RubyBoolean.newBoolean(getRuntime(), value == ((RubyNumeric) other)
.getDoubleValue());
return RubyBoolean.newBoolean(context.runtime, value == ((RubyNumeric) other).getDoubleValue());
default:
// Numeric.equal
// Numeric.equal
return super.op_num_equal(context, other);
}
}

public IRubyObject op_equal(ThreadContext context, double other) {
if (Double.isNaN(value)) {
return getRuntime().getFalse();
return context.runtime.getFalse();
}
return RubyBoolean.newBoolean(getRuntime(), value == other);
return RubyBoolean.newBoolean(context.runtime, value == other);
}

public boolean fastEqual(RubyFloat other) {
if (Double.isNaN(value)) {
return false;
}
return value == ((RubyFloat)other).value;
return value == other.value;
}

@Override
@@ -516,44 +511,37 @@ public final int compareTo(IRubyObject other) {
case FLOAT:
return Double.compare(value, ((RubyNumeric) other).getDoubleValue());
default:
return (int)coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
return (int) coerceCmp(getRuntime().getCurrentContext(), "<=>", other).convertToInteger().getLongValue();
}
}

/** flo_cmp
*
*
*/
@JRubyMethod(name = "<=>", required = 1)
public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
final Ruby runtime = context.runtime;
switch (other.getMetaClass().getClassIndex()) {
case FIXNUM:
case BIGNUM:
if (Double.isInfinite(value)) {
return value > 0.0 ? RubyFixnum.one(getRuntime()) : RubyFixnum.minus_one(getRuntime());
return value > 0.0 ? RubyFixnum.one(runtime) : RubyFixnum.minus_one(runtime);
}
case FLOAT:
double b = ((RubyNumeric) other).getDoubleValue();
return dbl_cmp(getRuntime(), value, b);
return dbl_cmp(runtime, value, b);
default:
if (Double.isInfinite(value) && other.respondsTo("infinite?")) {
IRubyObject infinite = other.callMethod(context, "infinite?");
if (infinite.isNil()) {
return value > 0.0 ? RubyFixnum.one(getRuntime()) : RubyFixnum.minus_one(getRuntime());
return value > 0.0 ? RubyFixnum.one(runtime) : RubyFixnum.minus_one(runtime);
} else {
int sign = RubyFixnum.fix2int(infinite);

if (sign > 0) {
if (value > 0.0) {
return RubyFixnum.zero(getRuntime());
} else {
return RubyFixnum.minus_one(getRuntime());
}
return value > 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.minus_one(runtime);
} else {
if (value < 0.0) {
return RubyFixnum.zero(getRuntime());
} else {
return RubyFixnum.one(getRuntime());
}
return value < 0.0 ? RubyFixnum.zero(runtime) : RubyFixnum.one(runtime);
}
}
}
@@ -562,11 +550,11 @@ public IRubyObject op_cmp(ThreadContext context, IRubyObject other) {
}

public IRubyObject op_cmp(ThreadContext context, double other) {
return dbl_cmp(getRuntime(), value, other);
return dbl_cmp(context.runtime, value, other);
}

/** flo_gt
*
*
*/
@JRubyMethod(name = ">", required = 1)
public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
@@ -575,18 +563,18 @@ public IRubyObject op_gt(ThreadContext context, IRubyObject other) {
case BIGNUM:
case FLOAT:
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(b) && value > b);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value > b);
default:
return coerceRelOp(context, ">", other);
}
}

public IRubyObject op_gt(ThreadContext context, double other) {
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(other) && value > other);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(other) && value > other);
}

/** flo_ge
*
*
*/
@JRubyMethod(name = ">=", required = 1)
public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
@@ -595,18 +583,18 @@ public IRubyObject op_ge(ThreadContext context, IRubyObject other) {
case BIGNUM:
case FLOAT:
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(b) && value >= b);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value >= b);
default:
return coerceRelOp(context, ">=", other);
}
}

public IRubyObject op_ge(ThreadContext context, double other) {
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(other) && value >= other);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(other) && value >= other);
}

/** flo_lt
*
*
*/
@JRubyMethod(name = "<", required = 1)
public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
@@ -615,18 +603,18 @@ public IRubyObject op_lt(ThreadContext context, IRubyObject other) {
case BIGNUM:
case FLOAT:
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(b) && value < b);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value < b);
default:
return coerceRelOp(context, "<", other);
}
}

public IRubyObject op_lt(ThreadContext context, double other) {
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(other) && value < other);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(other) && value < other);
}

/** flo_le
*
*
*/
@JRubyMethod(name = "<=", required = 1)
public IRubyObject op_le(ThreadContext context, IRubyObject other) {
@@ -635,18 +623,18 @@ public IRubyObject op_le(ThreadContext context, IRubyObject other) {
case BIGNUM:
case FLOAT:
double b = ((RubyNumeric) other).getDoubleValue();
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(b) && value <= b);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(b) && value <= b);
default:
return coerceRelOp(context, "<=", other);
}
}

public IRubyObject op_le(ThreadContext context, double other) {
return RubyBoolean.newBoolean(getRuntime(), !Double.isNaN(other) && value <= other);
return RubyBoolean.newBoolean(context.runtime, !Double.isNaN(other) && value <= other);
}

/** flo_eql
*
*
*/
@JRubyMethod(name = "eql?", required = 1)
@Override
@@ -658,16 +646,16 @@ public IRubyObject eql_p(IRubyObject other) {
public boolean equals(Object other) {
return (other instanceof RubyFloat) && equals((RubyFloat) other);
}

private boolean equals(RubyFloat that) {
if ( Double.isNaN(this.value) || Double.isNaN(that.value) ) return false;
final double val1 = this.value == -0.0 ? 0.0 : this.value;
final double val2 = that.value == -0.0 ? 0.0 : that.value;
return Double.doubleToLongBits(val1) == Double.doubleToLongBits(val2);
}

/** flo_hash
*
*
*/
@JRubyMethod(name = "hash")
@Override
@@ -683,15 +671,15 @@ public final int hashCode() {
}

/** flo_fo
*
*
*/
@JRubyMethod(name = "to_f")
public IRubyObject to_f() {
return this;
}

/** flo_abs
*
*
*/
@JRubyMethod(name = "abs")
@Override
@@ -703,7 +691,7 @@ public IRubyObject abs(ThreadContext context) {
}

/** flo_abs/1.9
*
*
*/
@JRubyMethod(name = "magnitude")
@Override
@@ -712,15 +700,15 @@ public IRubyObject magnitude(ThreadContext context) {
}

/** flo_zero_p
*
*
*/
@JRubyMethod(name = "zero?")
public IRubyObject zero_p() {
return RubyBoolean.newBoolean(getRuntime(), value == 0.0);
}

/** flo_truncate
*
*
*/
@JRubyMethod(name = {"truncate", "to_i", "to_int"})
@Override
@@ -733,7 +721,7 @@ public IRubyObject truncate() {
}

/** flo_numerator
*
*
*/
@JRubyMethod(name = "numerator")
@Override
@@ -743,7 +731,7 @@ public IRubyObject numerator(ThreadContext context) {
}

/** flo_denominator
*
*
*/
@JRubyMethod(name = "denominator")
@Override
@@ -755,13 +743,13 @@ public IRubyObject denominator(ThreadContext context) {
}

/** float_to_r, float_decode
*
*
*/
static final int DBL_MANT_DIG = 53;
static final int FLT_RADIX = 2;
@JRubyMethod(name = "to_r")
public IRubyObject to_r(ThreadContext context) {
long[]exp = new long[1];
long[] exp = new long[1];
double f = frexp(value, exp);
f = ldexp(f, DBL_MANT_DIG);
long n = exp[0] - DBL_MANT_DIG;
@@ -778,10 +766,11 @@ public IRubyObject to_r(ThreadContext context) {
*/
@JRubyMethod(name = "rationalize", optional = 1)
public IRubyObject rationalize(ThreadContext context, IRubyObject[] args) {
if (f_negative_p(context, this))
if (f_negative_p(context, this)) {
return f_negate(context, ((RubyFloat) f_abs(context, this)).rationalize(context, args));
}

Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
RubyFixnum one = RubyFixnum.one(runtime);
RubyFixnum two = RubyFixnum.two(runtime);

@@ -823,7 +812,7 @@ public IRubyObject rationalize(ThreadContext context, IRubyObject[] args) {
}

/** floor
*
*
*/
@JRubyMethod(name = "floor")
@Override
@@ -832,7 +821,7 @@ public IRubyObject floor() {
}

/** flo_ceil
*
*
*/
@JRubyMethod(name = "ceil")
@Override
@@ -841,29 +830,29 @@ public IRubyObject ceil() {
}

/** flo_round
*
*
*/
@Override
public IRubyObject round() {
return dbl2num(getRuntime(), val2dbl());
}

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

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

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

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

@@ -874,15 +863,15 @@ public IRubyObject round(ThreadContext context, IRubyObject[] args) {
} else {
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(context.runtime, number);
}
if (digits < -(binexp > 0 ? binexp / 3 + 1 : binexp / 4)) {
return dbl2num(context.runtime, (long) 0);
}

if (Double.isInfinite(magnifier)) {
if (digits < 0) number = 0;
} else {
@@ -899,20 +888,20 @@ public IRubyObject round(ThreadContext context, IRubyObject[] args) {
number /= magnifier;
}
}

if (digits > 0) {
return RubyFloat.newFloat(context.runtime, number);
} else {
if (number > Long.MAX_VALUE || number < Long.MIN_VALUE) {
// The only way to get huge precise values with BigDecimal is
// 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 dbl2num(context.runtime, (long)number);
}
}

private double val2dbl() {
double f = value;
if (f > 0.0) {
@@ -926,20 +915,20 @@ private double val2dbl() {
f -= 1.0;
}
}

return f;
}

/** flo_is_nan_p
*
*
*/
@JRubyMethod(name = "nan?")
public IRubyObject nan_p() {
return RubyBoolean.newBoolean(getRuntime(), Double.isNaN(value));
}

/** flo_is_infinite_p
*
*
*/
@JRubyMethod(name = "infinite?")
public IRubyObject infinite_p() {
@@ -948,9 +937,9 @@ public IRubyObject infinite_p() {
}
return getRuntime().getNil();
}

/** flo_is_finite_p
*
*
*/
@JRubyMethod(name = "finite?")
public IRubyObject finite_p() {
@@ -974,7 +963,7 @@ public static void marshalTo(RubyFloat aFloat, MarshalStream output) throws java
output.registerLinkTarget(aFloat);
output.writeString(aFloat.marshalDump());
}

public static RubyFloat unmarshalFrom(UnmarshalStream input) throws java.io.IOException {
ByteList value = input.unmarshalString();
RubyFloat result;