@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; } }
private IRubyObject stepCommon19(ThreadContext context, IRubyObject step, Block block) { Ruby runtime = context.getRuntime(); if (begin instanceof RubyFixnum && end instanceof RubyFixnum && step instanceof RubyFixnum) { fixnumStep(context, runtime, ((RubyFixnum) step).getLongValue(), block); } else if (begin instanceof RubyFloat || end instanceof RubyFloat || step instanceof RubyFloat) { RubyNumeric.floatStep19(context, runtime, begin, end, step, isExclusive, block); } else if (begin instanceof RubyNumeric || !checkIntegerType(runtime, begin, "to_int").isNil() || !checkIntegerType(runtime, end, "to_int").isNil()) { numericStep19(context, runtime, step, block); } else { IRubyObject tmp = begin.checkStringType(); if (!tmp.isNil()) { StepBlockCallBack callback = new StepBlockCallBack(block, RubyFixnum.one(runtime), step); Block blockCallback = CallBlock.newCallClosure( this, runtime.getRange(), Arity.singleArgument(), callback, context); ((RubyString) tmp).uptoCommon19(context, end, isExclusive, blockCallback); } else { if (!begin.respondsTo("succ")) throw runtime.newTypeError("can't iterate from " + begin.getMetaClass().getName()); // range_each_func(range, step_i, b, e, args); rangeEach(context, new StepBlockCallBack(block, RubyFixnum.one(runtime), step)); } } return this; }
private static void fixnumStep( ThreadContext context, Ruby runtime, long from, long to, long step, Block block) { // We must avoid integer overflows in "i += step". if (step >= 0) { long tov = Long.MAX_VALUE - step; if (to < tov) tov = to; long i; for (i = from; i <= tov; i += step) { block.yield(context, RubyFixnum.newFixnum(runtime, i)); } if (i <= to) { block.yield(context, RubyFixnum.newFixnum(runtime, i)); } } else { long tov = Long.MIN_VALUE - step; if (to > tov) tov = to; long i; for (i = from; i >= tov; i += step) { block.yield(context, RubyFixnum.newFixnum(runtime, i)); } if (i >= to) { block.yield(context, RubyFixnum.newFixnum(runtime, i)); } } }
private IRubyObject stepCommon(ThreadContext context, IRubyObject step, Block block) { final Ruby runtime = context.getRuntime(); long unit = RubyNumeric.num2long(step); if (unit < 0) throw runtime.newArgumentError("step can't be negative"); if (begin instanceof RubyFixnum && end instanceof RubyFixnum) { if (unit == 0) throw runtime.newArgumentError("step can't be 0"); fixnumStep(context, runtime, unit, block); } else { IRubyObject tmp = begin.checkStringType(); if (!tmp.isNil()) { if (unit == 0) throw runtime.newArgumentError("step can't be 0"); // rb_iterate((VALUE(*)_((VALUE)))str_step, (VALUE)args, step_i, (VALUE)iter); StepBlockCallBack callback = new StepBlockCallBack(block, RubyFixnum.one(runtime), step); Block blockCallback = CallBlock.newCallClosure( this, runtime.getRange(), Arity.singleArgument(), callback, context); ((RubyString) tmp).uptoCommon(context, end, isExclusive, blockCallback); } else if (begin instanceof RubyNumeric) { if (equalInternal(context, step, RubyFixnum.zero(runtime))) throw runtime.newArgumentError("step can't be 0"); numericStep(context, runtime, step, block); } else { if (unit == 0) throw runtime.newArgumentError("step can't be 0"); if (!begin.respondsTo("succ")) throw runtime.newTypeError("can't iterate from " + begin.getMetaClass().getName()); // range_each_func(range, step_i, b, e, args); rangeEach(context, new StepBlockCallBack(block, RubyFixnum.one(runtime), step)); } } return this; }
@JRubyMethod(name = "_id2ref", required = 1, module = true, visibility = Visibility.PRIVATE) public static IRubyObject id2ref(IRubyObject recv, IRubyObject id) { Ruby runtime = id.getRuntime(); if (!(id instanceof RubyFixnum)) { throw recv.getRuntime().newTypeError(id, recv.getRuntime().getFixnum()); } RubyFixnum idFixnum = (RubyFixnum) id; long longId = idFixnum.getLongValue(); if (longId == 0) { return runtime.getFalse(); } else if (longId == 2) { return runtime.getTrue(); } else if (longId == 4) { return runtime.getNil(); } else if (longId % 2 != 0) { // odd return runtime.newFixnum((longId - 1) / 2); } else { if (runtime.isObjectSpaceEnabled()) { IRubyObject object = runtime.getObjectSpace().id2ref(longId); if (object == null) { return runtime.getNil(); } return object; } else { runtime .getWarnings() .warn("ObjectSpace is disabled; _id2ref only supports immediates, pass -X+O to enable"); return runtime.getNil(); } } }
@Override public RubyFixnum id() { if ((flags & FALSE_F) == 0) { return RubyFixnum.newFixnum(getRuntime(), 2); } else { return RubyFixnum.zero(getRuntime()); } }
@JRubyMethod(name = "even?") public RubyBoolean even_p(ThreadContext context) { Ruby runtime = context.getRuntime(); if (callMethod(context, "%", RubyFixnum.two(runtime)) == RubyFixnum.zero(runtime)) { return runtime.getTrue(); } return runtime.getFalse(); }
@JRubyMethod(name = "odd?") public RubyBoolean odd_p(ThreadContext context) { Ruby runtime = context.runtime; if (callMethod(context, "%", RubyFixnum.two(runtime)) != RubyFixnum.zero(runtime)) { return runtime.getTrue(); } return runtime.getFalse(); }
/** int_succ */ @JRubyMethod(name = {"succ", "next"}) public IRubyObject succ(ThreadContext context) { if (this instanceof RubyFixnum) { return RubyFixnum.newFixnum(context.getRuntime(), getLongValue() + 1L); } else { return callMethod(context, "+", RubyFixnum.one(context.getRuntime())); } }
void call(ThreadContext context, IRubyObject arg) { if (iter instanceof RubyFixnum) { iter = RubyFixnum.newFixnum(context.getRuntime(), ((RubyFixnum) iter).getLongValue() - 1); } else { iter = iter.callMethod(context, "-", RubyFixnum.one(context.getRuntime())); } if (iter == RubyFixnum.zero(context.getRuntime())) { block.yield(context, arg); iter = step; } }
public WarningGlobalVariable( Ruby runtime, String name, RubyInstanceConfig.Verbosity verbosity) { super( runtime, name, verbosity == RubyInstanceConfig.Verbosity.NIL ? RubyFixnum.newFixnum(runtime, 0) : verbosity == RubyInstanceConfig.Verbosity.FALSE ? RubyFixnum.newFixnum(runtime, 1) : verbosity == RubyInstanceConfig.Verbosity.TRUE ? RubyFixnum.newFixnum(runtime, 2) : runtime.getNil()); }
@JRubyMethod(name = "to_r") public IRubyObject to_r(ThreadContext context) { long[] exp = new long[1]; double f = frexp(value, exp); f = ldexp(f, DBL_MANT_DIG); long n = exp[0] - DBL_MANT_DIG; Ruby runtime = context.runtime; IRubyObject rf = RubyNumeric.dbl2num(runtime, f); IRubyObject rn = RubyFixnum.newFixnum(runtime, n); return f_mul(context, rf, f_expt(context, RubyFixnum.newFixnum(runtime, FLT_RADIX), rn)); }
public static RubyClass createFloatClass(Ruby runtime) { RubyClass floatc = runtime.defineClass( "Float", runtime.getNumeric(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); runtime.setFloat(floatc); 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: 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 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)); floatc.defineConstant("MIN", RubyFloat.newFloat(runtime, Double.MIN_VALUE)); floatc.defineConstant("MAX", RubyFloat.newFloat(runtime, Double.MAX_VALUE)); floatc.defineConstant("EPSILON", RubyFloat.newFloat(runtime, EPSILON)); floatc.defineConstant("INFINITY", RubyFloat.newFloat(runtime, INFINITY)); floatc.defineConstant("NAN", RubyFloat.newFloat(runtime, NAN)); floatc.defineAnnotatedMethods(RubyFloat.class); return floatc; }
private void fixnumStep(ThreadContext context, Ruby runtime, long unit, Block block) { long e = ((RubyFixnum) end).getLongValue(); if (!isExclusive) e++; for (long i = ((RubyFixnum) begin).getLongValue(); i < e; i += unit) { block.yield(context, RubyFixnum.newFixnum(runtime, i)); } }
@Override public IRubyObject set(IRubyObject value) { runtime .getWarnings() .warnOnce(ID.SAFE_NOT_SUPPORTED, "SAFE levels are not supported in JRuby"); return RubyFixnum.zero(runtime); }
private IRubyObject rangeLe(ThreadContext context, IRubyObject a, IRubyObject b) { IRubyObject result = a.callMethod(context, "<=>", b); if (result.isNil()) return null; int c = RubyComparable.cmpint(context, result, a, b); if (c == 0) return RubyFixnum.zero(getRuntime()); return c < 0 ? getRuntime().getTrue() : null; }
/** num_cmp */ @JRubyMethod(name = "<=>") public IRubyObject op_cmp(IRubyObject other) { if (this == other) { // won't hurt fixnums return RubyFixnum.zero(getRuntime()); } return getRuntime().getNil(); }
/** num_abs */ @JRubyMethod(name = "abs") public IRubyObject abs(ThreadContext context) { if (callMethod(context, "<", RubyFixnum.zero(getRuntime())).isTrue()) { return callMethod(context, "-@"); } return this; }
/** flo_is_infinite_p */ @JRubyMethod(name = "infinite?") public IRubyObject infinite_p() { if (Double.isInfinite(value)) { return RubyFixnum.newFixnum(getRuntime(), value < 0 ? -1 : 1); } return getRuntime().getNil(); }
private static IRubyObject convertToNum(double val, Ruby runtime) { if (val >= (double) RubyFixnum.MAX || val < (double) RubyFixnum.MIN) { return RubyBignum.newBignum(runtime, val); } return RubyFixnum.newFixnum(runtime, (long) val); }
/** match_end */ @JRubyMethod(name = "end", compat = CompatVersion.RUBY1_8) public IRubyObject end(ThreadContext context, IRubyObject index) { int i = RubyNumeric.num2int(index); Ruby runtime = context.getRuntime(); int e = endCommon(runtime, i); return e < 0 ? runtime.getNil() : RubyFixnum.newFixnum(runtime, e); }
@JRubyMethod(name = "seek", required = 1, optional = 1, frame = true) public IRubyObject seek(IRubyObject[] args) { // MRI 1.8.7 behavior: // checkOpen(); checkFinalized(); long amount = RubyNumeric.num2long(args[0]); int whence = Stream.SEEK_SET; long newPosition = pos; if (args.length > 1 && !args[0].isNil()) whence = RubyNumeric.fix2int(args[1]); if (whence == Stream.SEEK_CUR) { newPosition += amount; } else if (whence == Stream.SEEK_END) { newPosition = internal.getByteList().length() + amount; } else { newPosition = amount; } if (newPosition < 0) throw getRuntime().newErrnoEINVALError(); pos = newPosition; eof = false; return RubyFixnum.zero(getRuntime()); }
@JRubyMethod(name = "initialize", optional = 2, frame = true, visibility = Visibility.PRIVATE) public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { Object modeArgument = null; switch (args.length) { case 0: internal = RubyString.newEmptyString(getRuntime()); modeArgument = "r+"; break; case 1: internal = args[0].convertToString(); modeArgument = internal.isFrozen() ? "r" : "r+"; break; case 2: internal = args[0].convertToString(); if (args[1] instanceof RubyFixnum) { modeArgument = RubyFixnum.fix2long(args[1]); } else { modeArgument = args[1].convertToString().toString(); } break; } initializeModes(modeArgument); if (modes.isWritable() && internal.isFrozen()) { throw getRuntime().newErrnoEACCESError("Permission denied"); } if (modes.isTruncate()) { internal.modifyCheck(); internal.empty(); } return this; }
/** float_rationalize */ @JRubyMethod(name = "rationalize", optional = 1) public IRubyObject rationalize(ThreadContext context, IRubyObject[] args) { if (f_negative_p(context, this)) return f_negate(context, ((RubyFloat) f_abs(context, this)).rationalize(context, args)); Ruby runtime = context.runtime; RubyFixnum one = RubyFixnum.one(runtime); RubyFixnum two = RubyFixnum.two(runtime); IRubyObject eps, a, b; if (args.length != 0) { eps = f_abs(context, args[0]); a = f_sub(context, this, eps); b = f_add(context, this, eps); } else { long[] exp = new long[1]; double f = frexp(value, exp); f = ldexp(f, DBL_MANT_DIG); long n = exp[0] - DBL_MANT_DIG; IRubyObject rf = RubyNumeric.dbl2num(runtime, f); IRubyObject rn = RubyFixnum.newFixnum(runtime, n); if (f_zero_p(context, rf) || !(f_negative_p(context, rn) || f_zero_p(context, rn))) return RubyRational.newRationalRaw(runtime, f_lshift(context, rf, rn)); a = RubyRational.newRationalRaw( runtime, f_sub(context, f_mul(context, two, rf), one), f_lshift(context, one, f_sub(context, one, rn))); b = RubyRational.newRationalRaw( runtime, f_add(context, f_mul(context, two, rf), one), f_lshift(context, one, f_sub(context, one, rn))); } if (invokedynamic(context, a, OP_EQUAL, b).isTrue()) return f_to_r(context, this); IRubyObject[] ary = new IRubyObject[2]; ary[0] = a; ary[1] = b; IRubyObject[] ans = nurat_rationalize_internal(context, ary); return RubyRational.newRationalRaw(runtime, ans[0], ans[1]); }
/** int_succ */ @JRubyMethod(name = {"succ", "next"}) public IRubyObject succ(ThreadContext context) { if (this instanceof RubyFixnum) { return ((RubyFixnum) this).op_plus_one(context); } else { return callMethod(context, "+", RubyFixnum.one(context.runtime)); } }
/** flo_denominator */ @JRubyMethod(name = "denominator") @Override public IRubyObject denominator(ThreadContext context) { if (Double.isInfinite(value) || Double.isNaN(value)) { return RubyFixnum.one(context.runtime); } return super.denominator(context); }
@JRubyMethod public IRubyObject times(ThreadContext context, Block block) { if (block.isGiven()) { Ruby runtime = context.getRuntime(); IRubyObject i = RubyFixnum.zero(runtime); RubyFixnum one = RubyFixnum.one(runtime); while (true) { if (!i.callMethod(context, "<", this).isTrue()) { break; } block.yield(context, i); i = i.callMethod(context, "+", one); } return this; } else { return enumeratorize(context.getRuntime(), this, "times"); } }
@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"); return this; } if (Double.isNaN(value)) { if (digits <= 0) throw getRuntime().newFloatDomainError("NaN"); return this; } // MRI flo_round logic to deal with huge precision numbers. double binexp = Math.ceil(Math.log(value) / Math.log(2)); 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 RubyFixnum.zero(context.runtime); } if (Double.isInfinite(magnifier)) { if (digits < 0) number = 0; } else { if (digits < 0) { number /= magnifier; } else { number *= magnifier; } number = Math.round(Math.abs(number)) * Math.signum(number); if (digits < 0) { number *= magnifier; } else { 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 // 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); } }
@JRubyMethod(name = "max", frame = true, compat = CompatVersion.RUBY1_9) public IRubyObject max(ThreadContext context, Block block) { if (block.isGiven() || isExclusive && !(end instanceof RubyNumeric)) { return RuntimeHelpers.invokeSuper(context, this, block); } else { int c = RubyComparable.cmpint(context, begin.callMethod(context, "<=>", end), begin, end); Ruby runtime = context.getRuntime(); if (isExclusive) { if (!(end instanceof RubyInteger)) throw runtime.newTypeError("cannot exclude non Integer end value"); if (c == 0) return runtime.getNil(); if (end instanceof RubyFixnum) return RubyFixnum.newFixnum(runtime, ((RubyFixnum) end).getLongValue() - 1); return end.callMethod(context, "-", RubyFixnum.one(runtime)); } return end; } }
/** num_step_scan_args */ private IRubyObject[] scanStepArgs(ThreadContext context, IRubyObject[] args) { IRubyObject to = context.runtime.getNil(); IRubyObject step = context.runtime.newFixnum(1); if (args.length >= 1) to = args[0]; if (args.length >= 2) step = args[1]; // TODO: Fold kwargs into the @JRubyMethod decorator IRubyObject[] kwargs = ArgsUtil.extractKeywordArgs(context, args, validStepArgs); if (kwargs != null) { to = kwargs[0]; step = kwargs[1]; if (!to.isNil() && args.length > 1) { throw context.runtime.newArgumentError("to is given twice"); } if (!step.isNil() && args.length > 2) { throw context.runtime.newArgumentError("step is given twice"); } } else { if (RubyBasicObject.equalInternal(context, step, RubyFixnum.zero(context.runtime))) { throw context.runtime.newArgumentError("step can't be 0"); } if (step.isNil()) { throw context.runtime.newTypeError("step must be numeric"); } } if (step.isNil()) { step = RubyFixnum.one(context.runtime); } if (to.isNil()) { if (f_negative_p(context, step)) { to = RubyFloat.newFloat(context.runtime, Double.NEGATIVE_INFINITY); } else { to = RubyFloat.newFloat(context.runtime, Double.POSITIVE_INFINITY); } } return new IRubyObject[] {to, step}; }