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

Commits on Aug 21, 2015

  1. Copy the full SHA
    06e4175 View commit details
  2. implement bigmath .exp

    ahorek committed Aug 21, 2015
    Copy the full SHA
    b6f29ef View commit details
  3. Copy the full SHA
    9c1fe2e View commit details
  4. implement bigdecimal .to_r

    ahorek committed Aug 21, 2015
    Copy the full SHA
    d2a1a93 View commit details
  5. Copy the full SHA
    b0dac00 View commit details
  6. BigDecimal('0.1').coerce(0.1) returns two bigdecimals not floats

    BigDecimal('0.1').coerce(10**(-1)) fix type error
    BigDecimal('0.1') == ((10**(-1))) should be true
    ahorek committed Aug 21, 2015
    Copy the full SHA
    73764ea View commit details
  7. more specs are passing

    ahorek committed Aug 21, 2015
    Copy the full SHA
    ac39239 View commit details
  8. Copy the full SHA
    fc5be98 View commit details
  9. fix log positive infinity

    ahorek committed Aug 21, 2015
    Copy the full SHA
    efd173e View commit details
  10. increase precision

    ahorek committed Aug 21, 2015
    Copy the full SHA
    e1ad735 View commit details
  11. input should be numeric

    ahorek committed Aug 21, 2015
    Copy the full SHA
    52db7e9 View commit details
  12. Merge pull request #3271 from ahorek/bigdecimal_and_bigmath

    bigdecimal & bigmath
    enebo committed Aug 21, 2015
    Copy the full SHA
    3584f55 View commit details
45 changes: 40 additions & 5 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -465,6 +465,9 @@ private static RubyBigDecimal getVpValue(ThreadContext context, IRubyObject valu
// Converted to a String because some values -inf cannot happen from Java libs
return newInstance(context, context.runtime.getClass("BigDecimal"), value.asString());
}
if ((value instanceof RubyRational) || (value instanceof RubyFloat)) {
return newInstance(context, context.runtime.getClass("BigDecimal"), value, RubyFixnum.newFixnum(context.runtime, RubyFloat.DIG));
}
return cannotBeCoerced(context, value, must);
}

@@ -493,7 +496,10 @@ private static RubyBigDecimal newInstance(Ruby runtime, IRubyObject recv, RubyFl
// precision can be no more than float digits
if (mathContext.getPrecision() > RubyFloat.DIG + 1) throw runtime.newArgumentError("precision too large");

return new RubyBigDecimal(runtime, (RubyClass) recv, new BigDecimal(arg.getDoubleValue(), mathContext));
double dblVal = arg.getDoubleValue();
if(Double.isInfinite(dblVal) || Double.isNaN(dblVal)) throw runtime.newFloatDomainError("NaN");

return new RubyBigDecimal(runtime, (RubyClass) recv, new BigDecimal(dblVal, mathContext));
}

private static RubyBigDecimal newInstance(Ruby runtime, IRubyObject recv, RubyBignum arg, MathContext mathContext) {
@@ -600,7 +606,8 @@ public static RubyBigDecimal newInstance(IRubyObject recv, IRubyObject[] args) {
@JRubyMethod(name = "new", meta = true)
public static RubyBigDecimal newInstance(ThreadContext context, IRubyObject recv, IRubyObject arg) {
if (arg instanceof RubyBigDecimal) return newInstance(context.runtime, recv, (RubyBigDecimal) arg);
if (arg instanceof RubyFloat || arg instanceof RubyRational) throw context.runtime.newArgumentError("can't omit precision for a rational");
if (arg instanceof RubyRational) throw context.runtime.newArgumentError("can't omit precision for a Rational.");
if (arg instanceof RubyFloat) throw context.runtime.newArgumentError("can't omit precision for a Float.");
if (arg instanceof RubyFixnum) return newInstance(context.runtime, recv, (RubyFixnum) arg, MathContext.UNLIMITED);
if (arg instanceof RubyBignum) return newInstance(context.runtime, recv, (RubyBignum) arg, MathContext.UNLIMITED);
return newInstance(context, recv, arg, MathContext.UNLIMITED);
@@ -1192,9 +1199,6 @@ public IRubyObject coerce(IRubyObject other) {

@JRubyMethod
public RubyArray coerce(ThreadContext context, IRubyObject other) {
if (other instanceof RubyFloat) {
return context.runtime.newArray(other, to_f());
}
return context.runtime.newArray(getVpValue(context, other, true), this);
}

@@ -1518,6 +1522,37 @@ public IRubyObject to_int() {
}
}

@JRubyMethod(name = "to_r")
public IRubyObject to_r(ThreadContext context) {
checkFloatDomain();

RubyArray i = split(context);
long sign = (long)i.get(0);
String digits = (String)i.get(1).toString();
long base = (long)i.get(2);
long power = (long)i.get(3);
long denomi_power = power - digits.length();

IRubyObject bigDigits = RubyBignum.newBignum(getRuntime(), (String)digits).op_mul(context, sign);
RubyBignum numerator;
if(bigDigits instanceof RubyBignum) {
numerator = (RubyBignum)bigDigits;
}
else {
numerator = RubyBignum.newBignum(getRuntime(), bigDigits.toString());
}
IRubyObject num, den;
if(denomi_power < 0) {
num = numerator;
den = RubyFixnum.newFixnum(getRuntime(), base).op_mul(context, RubyFixnum.newFixnum(getRuntime(), -denomi_power));
}
else {
num = numerator.op_pow(context, RubyFixnum.newFixnum(getRuntime(), base).op_mul(context, RubyFixnum.newFixnum(getRuntime(), denomi_power)));
den = RubyFixnum.newFixnum(getRuntime(), 1);
}
return RubyRational.newInstance(context, context.runtime.getRational(), num, den);
}

public IRubyObject to_int19() {
return to_int();
}
62 changes: 50 additions & 12 deletions core/src/main/ruby/jruby/bigdecimal.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require 'bigdecimal'
require 'bigdecimal/util'

module BigMath
module_function

# call-seq:
# log(decimal, numeric) -> BigDecimal
#
@@ -18,24 +19,27 @@ module BigMath
# BigMath::log(BigMath::E(10), 10).to_s
# #=> "1.000000000000"
#
def log(x, precision)
raise ArgumentError if x.nil?
raise Math::DomainError if x.is_a?(Complex)
raise Math::DomainError if x <= 0
raise ArgumentError unless precision.is_a?(Integer)
raise ArgumentError if precision < 1
return BigDecimal::INFINITY if x == BigDecimal::INFINITY
return BigDecimal::NAN if x.is_a?(BigDecimal) && x.nan?
return BigDecimal::NAN if x.is_a?(Float) && x.nan?
def log(x, prec)
raise ArgumentError if x.nil? || !x.is_a?(Numeric)
raise Math::DomainError if x.is_a?(Complex) || x <= 0
raise ArgumentError unless (true if Integer(prec) rescue false)
prec = prec.to_i
raise ArgumentError if prec < 1
if x.is_a?(BigDecimal) || x.is_a?(Float)
return BigDecimal::INFINITY if x.infinite?
return BigDecimal::NAN if x.nan?
end
x = x.is_a?(Rational) ? x.to_d(Float::DIG) : x.to_d
return BigDecimal::INFINITY if x.infinite?
return BigDecimal::NAN if x.nan?

# this uses the series expansion of the Arctangh (Arc tangens hyperbolicus)
# http://en.wikipedia.org/wiki/Area_hyperbolic_tangent
# where ln(x) = 2 * artanh ((x - 1) / (x + 1))
# d are the elements in the series (getting smaller and smaller)

x = x.to_d
rmpd_double_figures = 16 # from MRI ruby
n = precision + rmpd_double_figures
n = prec + rmpd_double_figures

# offset the calculation to the efficient (0.1)...(10) window
expo = x.exponent
@@ -72,4 +76,38 @@ def log(x, precision)
window_result
end
end

def exp(x, prec)
raise ArgumentError if x.nil? || !x.is_a?(Numeric) || x.is_a?(Complex)
raise ArgumentError unless (true if Integer(prec) rescue false)
prec = prec.to_i
raise ArgumentError if prec < 1
return BigDecimal::NAN if x.is_a?(BigDecimal) && x.nan?
return BigDecimal::NAN if x.is_a?(Float) && x.nan?
x = x.is_a?(Rational) ? x.to_d(Float::DIG) : x.to_d
return BigDecimal::NAN if x.nan?
return x.sign > 0 ? BigDecimal::INFINITY : BigDecimal(0, prec) if x.infinite?

df = BigDecimal.double_fig
n = prec + df
one = BigDecimal(1)
x = -x if neg = x.sign < 0

y = one;
d = y;
i = 1;

while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
m = df if m < df
d = d.mult(x, n)
d = d.div(i, m)
y += d
i += 1;
end
if neg
one.div(y, prec)
else
y.round(prec - y.exponent)
end
end
end
16 changes: 1 addition & 15 deletions lib/ruby/stdlib/bigdecimal/math.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
require 'bigdecimal'
require 'bigdecimal/util'

#
#--
@@ -227,19 +226,6 @@ def PI(prec)
#
def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
n = prec + BigDecimal.double_fig
one = BigDecimal("1")
y = one
d = y
z = one
i = 0
while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0)
m = BigDecimal.double_fig if m < BigDecimal.double_fig
i += 1
z *= i
d = one.div(z,m)
y += d
end
y
BigMath.exp(1, prec)
end
end
22 changes: 1 addition & 21 deletions test/mri/excludes/TestBigDecimal.rb
Original file line number Diff line number Diff line change
@@ -1,36 +1,18 @@
exclude :test_exception_overflow, "runs forever"
exclude :test_BigMath_exp, "needs investigation"
exclude :test_BigMath_exp_with_fixnum, "needs investigation"
exclude :test_BigMath_exp_with_float, "needs investigation"
exclude :test_BigMath_exp_with_rational, "needs investigation"

exclude :test_BigMath_exp_under_gc_stress, "needs investigation"
exclude :test_BigMath_log_under_gc_stress, "needs investigation"
exclude :test_dup, "needs investigation"
exclude :test_dup_subclass, "needs investigation"
exclude :test_div, "needs investigation"
exclude :test_exception_underflow, "needs investigation"

exclude :test_exp_with_1, "needs investigation"
exclude :test_exp_with_complex, "needs investigation"
exclude :test_exp_with_nan, "needs investigation"
exclude :test_exp_with_negative_infinite, "needs investigation"
exclude :test_exp_with_negative_precision, "needs investigation"
exclude :test_exp_with_positive_infinite, "needs investigation"
exclude :test_exp_with_zerp_precision, "needs investigation"

exclude :test_global_new, "runs forever"
exclude :test_global_new_with_float, "needs investigation"
exclude :test_limit, "needs investigation"
exclude :test_marshal, "needs investigation"
exclude :test_new, "needs investigation"

exclude :test_power_of_finite_with_zero, "needs investigation"
exclude :test_power_of_nan, "needs investigation"
exclude :test_power_of_negative_infinity, "needs investigation"
exclude :test_power_of_positive_infinity, "needs investigation"
exclude :test_power_of_three, "needs investigation"
exclude :test_power_of_zero, "needs investigation"
exclude :test_power_with_BigDecimal, "needs investigation"
exclude :test_power_with_Bignum, "needs investigation"
exclude :test_power_with_prec, "needs investigation"
exclude :test_power_without_prec, "needs investigation"
@@ -44,6 +26,4 @@
exclude :test_to_special_string, "needs investigation"
exclude :test_zero_p, "needs investigation"
exclude :test_add, "needs investigation"
exclude :test_cmp, "needs investigation"
exclude :test_coerce, "needs investigation"
exclude :test_ctov, "needs investigation"