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

Commits on Apr 9, 2018

  1. Copy the full SHA
    3bd3ed1 View commit details
  2. Copy the full SHA
    33e695a View commit details
  3. Copy the full SHA
    4ceea23 View commit details
  4. Copy the full SHA
    e4a5444 View commit details
  5. Copy the full SHA
    895379d View commit details
  6. Copy the full SHA
    c16eb4c View commit details
  7. Copy the full SHA
    79c176d View commit details
  8. 5
    Copy the full SHA
    31ed5e8 View commit details
28 changes: 22 additions & 6 deletions core/src/main/java/org/jruby/RubyBignum.java
Original file line number Diff line number Diff line change
@@ -283,7 +283,7 @@ public IRubyObject ceil(ThreadContext context, IRubyObject arg){
BigInteger exp = BigInteger.TEN.pow(posdigits);
BigInteger mod = self.mod(exp);
BigInteger res = self;
if (mod.compareTo(BigInteger.ZERO) != 0) {
if (mod.signum() != 0) {
res = self.add( exp.subtract(mod) );// self + (exp - (mod));
}
return newBignum(context.runtime, res);
@@ -348,21 +348,21 @@ public RubyArray digits(ThreadContext context, IRubyObject base) {
bigBase = long2big( ((RubyFixnum) base).getLongValue() );
}

if (bigBase.compareTo(BigInteger.ZERO) == -1) {
if (bigBase.signum() == -1) {
throw runtime.newArgumentError("negative radix");
}
if (bigBase.compareTo(new BigInteger("2")) == -1) {
if (bigBase.compareTo(BigInteger.valueOf(2)) == -1) {
throw runtime.newArgumentError("invalid radix: " + bigBase);
}

RubyArray res = RubyArray.newArray(context.runtime, 0);

if (self.compareTo(BigInteger.ZERO) == 0) {
if (self.signum() == 0) {
res.append(RubyFixnum.newFixnum(context.getRuntime(), 0));
return res;
}

while (self.compareTo(BigInteger.ZERO) > 0) {
while (self.signum() > 0) {
BigInteger q = self.mod(bigBase);
res.append(RubyBignum.newBignum(context.getRuntime(), q));
self = self.divide(bigBase);
@@ -909,6 +909,16 @@ public RubyInteger op_rshift(ThreadContext context, long shift) {
return bignorm(context.runtime, value.shiftRight((int) shift));
}

@Override
public RubyBoolean odd_p(ThreadContext context) {
return value.testBit(0) ? context.tru : context.fals;
}

@Override
public RubyBoolean even_p(ThreadContext context) {
return value.testBit(0) ? context.fals : context.tru;
}

/** rb_big_aref
*
*/
@@ -1033,6 +1043,12 @@ public IRubyObject to_f(ThreadContext context) {
return RubyFloat.newFloat(context.runtime, getDoubleValue());
}

@Override
public IRubyObject to_f() {
return RubyFloat.newFloat(getRuntime(), getDoubleValue());
}

@Deprecated
public IRubyObject abs() {
return abs(getRuntime().getCurrentContext());
}
@@ -1102,7 +1118,7 @@ public static RubyNumeric unmarshalFrom(UnmarshalStream input) throws IOExceptio
byte[] digits = new byte[shortLength * 2 + 1];

for (int i = digits.length - 1; i >= 1; i--) {
digits[i] = input.readSignedByte();
digits[i] = input.readSignedByte();
}

BigInteger value = new BigInteger(digits);
15 changes: 7 additions & 8 deletions core/src/main/java/org/jruby/RubyFixnum.java
Original file line number Diff line number Diff line change
@@ -656,18 +656,12 @@ public IRubyObject op_div(ThreadContext context, long other) {

@Override
public RubyBoolean odd_p(ThreadContext context) {
if(value%2 != 0) {
return context.runtime.getTrue();
}
return context.runtime.getFalse();
return (value & 1) != 0 ? context.tru : context.fals;
}

@Override
public RubyBoolean even_p(ThreadContext context) {
if(value%2 == 0) {
return context.runtime.getTrue();
}
return context.runtime.getFalse();
return (value & 1) == 0 ? context.tru : context.fals;
}

public IRubyObject pred(ThreadContext context) {
@@ -1317,6 +1311,11 @@ public IRubyObject op_rshift(long width) {
*/
@Override
public IRubyObject to_f(ThreadContext context) {
return RubyFloat.newFloat(context.runtime, (double) value);
}

@Override
public IRubyObject to_f() {
return RubyFloat.newFloat(getRuntime(), (double) value);
}

16 changes: 8 additions & 8 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -1139,14 +1139,14 @@ public double getDoubleValue() {
return getDoubleValue(getRuntime().getCurrentContext());
}

private static long ML = (long)(Math.log(Double.MAX_VALUE) / Math.log(2.0) - 1);
private static final long ML = (long)(Math.log(Double.MAX_VALUE) / Math.log(2.0) - 1);

public double getDoubleValue(ThreadContext context) {
Ruby runtime = context.runtime;

if (f_zero_p(context, num)) return 0;

IRubyObject myNum = this.num;
IRubyObject myDen = this.den;
RubyInteger myNum = this.num;
RubyInteger myDen = this.den;

boolean minus = false;
if (f_negative_p(context, myNum)) {
@@ -1160,19 +1160,19 @@ public double getDoubleValue(ThreadContext context) {
long ne = 0;
if (nl > ML) {
ne = nl - ML;
myNum = f_rshift(context, myNum, RubyFixnum.newFixnum(runtime, ne));
myNum = myNum.op_rshift(context, ne);
}

long de = 0;
if (dl > ML) {
de = dl - ML;
myDen = f_rshift(context, myDen, RubyFixnum.newFixnum(runtime, de));
myDen = myDen.op_rshift(context, de);
}

long e = ne - de;

if (e > 1023 || e < -1022) {
runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
context.runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
return e > 0 ? Double.MAX_VALUE : 0;
}

@@ -1183,7 +1183,7 @@ public double getDoubleValue(ThreadContext context) {
f = ldexp(f, e);

if (Double.isInfinite(f) || Double.isNaN(f)) {
runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
context.runtime.getWarnings().warn(IRubyWarnings.ID.FLOAT_OUT_OF_RANGE, "out of Float range");
}

return f;
71 changes: 34 additions & 37 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -126,7 +126,6 @@ public RubyBigDecimal allocate(Ruby runtime, RubyClass klass) {
public final static int EXCEPTION_NaN = 2;

// Static constants
private static final BigDecimal TWO = new BigDecimal(2);
private static final double SQRT_10 = 3.162277660168379332;

public static RubyClass createBigDecimal(Ruby runtime) {
@@ -151,8 +150,8 @@ public static RubyClass createBigDecimal(Ruby runtime) {
}

private boolean isNaN;
private int infinitySign;
private int zeroSign;
private int infinitySign; // 0 (for finite), -1, +1
private int zeroSign; // -1, +1 (if zero, otherwise 0)
private BigDecimal value;

public BigDecimal getValue() {
@@ -184,11 +183,7 @@ public RubyBigDecimal(Ruby runtime, RubyClass klass, BigDecimal value) {
}

public RubyBigDecimal(Ruby runtime, BigDecimal value, int infinitySign) {
super(runtime, runtime.getClass("BigDecimal"));
this.isNaN = false;
this.infinitySign = infinitySign;
this.zeroSign = 0;
this.value = value;
this(runtime, value, infinitySign, 0);
}

public RubyBigDecimal(Ruby runtime, BigDecimal value, int infinitySign, int zeroSign) {
@@ -386,13 +381,9 @@ public static IRubyObject mode(ThreadContext context, IRubyObject recv, IRubyObj
throw runtime.newTypeError("first argument for BigDecimal#mode invalid");
}

private static RubyModule bigDecimal(Ruby runtime) {
return runtime.getClass("BigDecimal");
}

// The Fixnum cast should be fine because these are internal variables and user code cannot change them.
private static long bigDecimalVar(Ruby runtime, String variableName) {
return ((RubyFixnum) bigDecimal(runtime).searchInternalModuleVariable(variableName)).getLongValue();
return ((RubyFixnum) runtime.getClass("BigDecimal").searchInternalModuleVariable(variableName)).getLongValue();
}

private static RoundingMode getRoundingMode(Ruby runtime) {
@@ -740,7 +731,7 @@ private static RubyBigDecimal newInfinity(final Ruby runtime, final int sign) {
if ( isInfinityExceptionMode(runtime) ) {
throw runtime.newFloatDomainError("Computation results to 'Infinity'");
}
return new RubyBigDecimal(runtime, BigDecimal.ZERO, sign < 0 ? -1 : 1);
return new RubyBigDecimal(runtime, BigDecimal.ZERO, sign < 0 ? -1 : 1, 0);
}

private RubyBigDecimal setResult() {
@@ -848,12 +839,11 @@ public IRubyObject mult2(ThreadContext context, IRubyObject b, IRubyObject n) {
}

private RubyBigDecimal multInternal(final Ruby runtime, RubyBigDecimal val, IRubyObject n) {
int digits = RubyNumeric.fix2int(n);

if (isNaN() || val.isNaN()) return newNaN(runtime);
if ((isInfinity() && val.isZero()) || (isZero() && val.isInfinity())) return newNaN(runtime);
if ( isNaN() || val.isNaN() ) return newNaN(runtime);

if ( isZero() || val.isZero() ) {
if ((isInfinity() && val.isZero()) || (isZero() && val.isInfinity())) return newNaN(runtime);

int sign1 = isZero()? zeroSign : value.signum();
int sign2 = val.isZero() ? val.zeroSign : val.value.signum();
return newZero(runtime, sign1 * sign2);
@@ -865,11 +855,9 @@ private RubyBigDecimal multInternal(final Ruby runtime, RubyBigDecimal val, IRub
return newInfinity(runtime, sign1 * sign2);
}

final int digits = RubyNumeric.fix2int(n);
BigDecimal res = value.multiply(val.value);
// FIXME: rounding mode should not be hard-coded. See #mode.
if (res.precision() > digits) res = res.round(new MathContext(digits, RoundingMode.HALF_UP));

return new RubyBigDecimal(runtime, res).setResult();
return new RubyBigDecimal(runtime, res).setResult(digits);
}

@Deprecated
@@ -883,14 +871,14 @@ private RubyBigDecimal newPowOfInfinity(ThreadContext context, RubyNumeric exp)
if (infinitySign >= 0) return newZero(context.runtime, 0);

// (-Infinity) ** (-even_integer) -> +0 AND (-Infinity) ** (-odd_integer) -> -0
if (Numeric.f_integer_p(context, exp)) return newZero(context.runtime, is_even(exp) ? 1 : -1);
if (Numeric.f_integer_p(context, exp)) return newZero(context.runtime, isEven(exp) ? 1 : -1);

return newZero(context.runtime, -1); // (-Infinity) ** (-non_integer) -> -0
}

if (infinitySign >= 0) return newInfinity(context.runtime, 1);

if (Numeric.f_integer_p(context, exp)) return newInfinity(context.runtime, is_even(exp) ? 1 : -1);
if (Numeric.f_integer_p(context, exp)) return newInfinity(context.runtime, isEven(exp) ? 1 : -1);

throw context.runtime.newMathDomainError("a non-integral exponent for a negative base");
}
@@ -1000,8 +988,8 @@ private IRubyObject addInternal(ThreadContext context, RubyBigDecimal val, IRuby
final Ruby runtime = context.runtime;
int prec = getPositiveInt(context, digits);

RoundingMode roundMode = getRoundingMode(runtime);
return new RubyBigDecimal(runtime, value.add(val.value, new MathContext(prec, roundMode)));
MathContext mathContext = new MathContext(prec, getRoundingMode(runtime));
return new RubyBigDecimal(runtime, value.add(val.value, mathContext)).setResult(prec);
}

private static int getPositiveInt(ThreadContext context, IRubyObject arg) {
@@ -1119,16 +1107,16 @@ public IRubyObject op_quo(ThreadContext context, IRubyObject other) {
return quoImpl(context, val);
}

private RubyBigDecimal quoImpl(ThreadContext context, RubyBigDecimal val) {
private RubyBigDecimal quoImpl(ThreadContext context, RubyBigDecimal that) {
// regular division with some default precision
// proper algorithm to set the precision
// the precision is multiple of 4
// and the precision is larger than len * 2
int len = value.precision() + val.value.precision();
int len = this.value.precision() + that.value.precision();
int scale = (len / 4 + 1) * 4 * 2;

MathContext mathContext = new MathContext(scale, getRoundingMode(context.runtime));
return new RubyBigDecimal(context.runtime, value.divide(val.value, mathContext)).setResult(scale);
return new RubyBigDecimal(context.runtime, this.value.divide(that.value, mathContext)).setResult();
}

@Deprecated
@@ -1736,15 +1724,21 @@ private String unscaledValue() {
return value.abs().unscaledValue().toString();
}

private static String sign(String arg, int signum) {
return signum == -1 ? "-" : (signum == 1 ? (posSign(arg) ? (posSpace(arg) ? " " : "+") : "") : "");
private static StringBuilder appendSign(final StringBuilder buff, final String str, int signum) {
if (signum == -1) buff.append('-');
else if (signum == 1) {
if (posSign(str)) {
buff.append(posSpace(str) ? ' ' : '+');
}
}
return buff;
}

private CharSequence engineeringValue(final String arg) {
final String s = removeTrailingZeroes(unscaledValue());

StringBuilder build = new StringBuilder();
build.append( sign(arg, value.signum()) ).append("0.");
appendSign(build, arg, value.signum()).append('0').append('.');

final int groups = groups(arg);
if (groups == 0) {
@@ -1768,7 +1762,7 @@ private CharSequence floatingPointValue(final String arg) {
final String after = values.size() > 1 ? values.get(1) : "0";

StringBuilder build = new StringBuilder();
build.append( sign(arg, value.signum()) );
appendSign(build, arg, value.signum());

final int groups = groups(arg);
if (groups == 0) {
@@ -1945,6 +1939,8 @@ public static BigDecimal bigSqrt(BigDecimal squarD, MathContext rootMC) {
return x.round(rootMC); // return small prec roots without iterations
}

final BigDecimal TWO = BigDecimal.valueOf(2);

// Initial v - the reciprocal
BigDecimal v = BigDecimal.ONE.divide(TWO.multiply(x), nMC); // v0 = 1/(2*x)

@@ -1990,10 +1986,11 @@ private String infinityString() {
return infinitySign == -1 ? "-Infinity" : "Infinity";
}

private static boolean is_even(final RubyNumeric x) {
if (x instanceof RubyFixnum) return RubyNumeric.fix2long((RubyFixnum) x) % 2 == 0;
if (x instanceof RubyBignum) return RubyBignum.big2long((RubyBignum) x) % 2 == 0;

private static boolean isEven(final RubyNumeric x) {
if (x instanceof RubyFixnum) return (((RubyFixnum) x).getLongValue() & 1) == 0;
if (x instanceof RubyBignum) {
return ((RubyBignum) x).getBigIntegerValue().testBit(0) == false; // 0-th bit -> 0
}
return false;
}

10 changes: 7 additions & 3 deletions core/src/main/java/org/jruby/util/Numeric.java
Original file line number Diff line number Diff line change
@@ -577,13 +577,17 @@ public static IRubyObject f_lcm(ThreadContext context, IRubyObject x, IRubyObjec
}

public static long i_ilog2(ThreadContext context, IRubyObject x) {
long q = (sites(context).size.call(context, x, x).convertToInteger().getLongValue() - 8) * 8 + 1;
return i_ilog2(context, x.convertToInteger());
}

public static long i_ilog2(ThreadContext context, RubyInteger x) {
long q = (x.size(context).convertToInteger().getLongValue() - 8) * 8 + 1;

if (q > 0) {
x = f_rshift(context, x, RubyFixnum.newFixnum(context.runtime, q));
x = x.op_rshift(context, q);
}

long fx = x.convertToInteger().getLongValue();
long fx = x.getLongValue();
long r = -1;

while (fx != 0) {
10 changes: 10 additions & 0 deletions spec/ruby/library/bigdecimal/limit_spec.rb
Original file line number Diff line number Diff line change
@@ -42,4 +42,14 @@
BigDecimal('0.888').div(BigDecimal('3'), 2).should == BigDecimal('0.30')
end
end

it "picks the global precision when limit 0 specified" do
BigDecimalSpecs.with_limit(3) do
BigDecimal('0.8888').add(BigDecimal('0'), 0).should == BigDecimal('0.889')
BigDecimal('0.8888').sub(BigDecimal('0'), 0).should == BigDecimal('0.889')
BigDecimal('0.888').mult(BigDecimal('3'), 0).should == BigDecimal('2.66')
BigDecimal('0.8888').div(BigDecimal('3'), 0).should == BigDecimal('0.296')
end
end

end