public static RubyNumeric intervalStepSize( ThreadContext context, IRubyObject from, IRubyObject to, IRubyObject step, boolean excludeLast) { Ruby runtime = context.runtime; if (from instanceof RubyFixnum && to instanceof RubyFixnum && step instanceof RubyFixnum) { long diff = ((RubyFixnum) step).getLongValue(); if (diff == 0) { return RubyFloat.newFloat(runtime, Double.POSITIVE_INFINITY); } long delta = ((RubyFixnum) to).getLongValue() - ((RubyFixnum) from).getLongValue(); if (diff < 0) { diff = -diff; delta = -delta; } if (excludeLast) { delta--; } if (delta < 0) { return runtime.newFixnum(0); } long result = delta / diff; return new RubyFixnum(runtime, result >= 0 ? result + 1 : 0); } else if (from instanceof RubyFloat || to instanceof RubyFloat || step instanceof RubyFloat) { double n = floatStepSize( from.convertToFloat().getDoubleValue(), to.convertToFloat().getDoubleValue(), step.convertToFloat().getDoubleValue(), excludeLast); if (Double.isInfinite(n)) { return runtime.newFloat(n); } else { return runtime.newFloat(n).convertToInteger(); } } else { String cmpString = ">"; RubyFixnum zero = RubyFixnum.zero(runtime); IRubyObject comparison = zero.coerceCmp(context, "<=>", step); switch (RubyComparable.cmpint(context, comparison, step, zero)) { case 0: return RubyFloat.newFloat(runtime, Float.POSITIVE_INFINITY); case 1: cmpString = "<"; break; } if (from.callMethod(context, cmpString, to).isTrue()) { return RubyFixnum.zero(runtime); } IRubyObject diff = to.callMethod(context, "-", from); IRubyObject result = diff.callMethod(context, "div", step); if (!excludeLast || from.callMethod(context, "+", result.callMethod(context, "*", step)) .callMethod(context, cmpString, to) .isTrue()) { result = result.callMethod(context, "+", RubyFixnum.newFixnum(runtime, 1)); } return (RubyNumeric) result; } }