@JRubyMethod(name = "round", compat = CompatVersion.RUBY1_9) public IRubyObject round19(ThreadContext context, IRubyObject arg) { int ndigits = RubyNumeric.num2int(arg); if (ndigits > 0) return RubyKernel.new_float(this, this); if (ndigits == 0) return this; ndigits = -ndigits; Ruby runtime = context.getRuntime(); if (ndigits < 0) throw runtime.newArgumentError("ndigits out of range"); IRubyObject f = Numeric.int_pow(context, 10, ndigits); if (this instanceof RubyFixnum && f instanceof RubyFixnum) { long x = ((RubyFixnum) this).getLongValue(); long y = ((RubyFixnum) f).getLongValue(); boolean neg = x < 0; if (neg) x = -x; x = (x + y / 2) / y * y; if (neg) x = -x; return RubyFixnum.newFixnum(runtime, x); } else { IRubyObject h = f.callMethod(context, "/", RubyFixnum.two(runtime)); IRubyObject r = callMethod(context, "%", f); IRubyObject n = callMethod(context, "-", r); if (!r.callMethod(context, "<", h).isTrue()) n = n.callMethod(context, "+", f); return n; } }
@JRubyMethod(name = "round", compat = CompatVersion.RUBY1_9) public IRubyObject round19(ThreadContext context, IRubyObject arg) { int ndigits = RubyNumeric.num2int(arg); if (ndigits > 0) return RubyKernel.new_float(this, this); if (ndigits == 0) return this; Ruby runtime = context.runtime; long bytes = (this instanceof RubyFixnum) ? 8 : RubyFixnum.fix2long(callMethod("size")); /* If 10**N/2 > this, return 0 */ /* We have log_256(10) > 0.415241 and log_256(1/2)=-0.125 */ if (-0.415241 * ndigits - 0.125 > bytes) { return RubyFixnum.zero(runtime); } IRubyObject f = Numeric.int_pow(context, 10, -ndigits); if (this instanceof RubyFixnum && f instanceof RubyFixnum) { long x = ((RubyFixnum) this).getLongValue(); long y = ((RubyFixnum) f).getLongValue(); boolean neg = x < 0; if (neg) x = -x; x = (x + y / 2) / y * y; if (neg) x = -x; return RubyFixnum.newFixnum(runtime, x); } else if (f instanceof RubyFloat) { return RubyFixnum.zero(runtime); } else { IRubyObject h = f.callMethod(context, "/", RubyFixnum.two(runtime)); IRubyObject r = callMethod(context, "%", f); IRubyObject n = callMethod(context, "-", r); String op = callMethod(context, "<", RubyFixnum.zero(runtime)).isTrue() ? "<=" : "<"; if (!r.callMethod(context, op, h).isTrue()) n = n.callMethod(context, "+", f); return n; } }