module Rubinius class Mirror class Numeric < Mirror self.subject = ::Numeric def step_float_size(value, limit, step, asc) if (asc && value > limit) || (!asc && value < limit) return 0 end if step.infinite? 1 else err = (value.abs + limit.abs + (limit - value).abs) / step.abs * Float::EPSILON if err.finite? err = 0.5 if err > 0.5 ((limit - value) / step + err).floor + 1 else 0 end end end def step_size(limit, step, to, by) values = step_fetch_args(limit, step, to, by) value = values[0] limit = values[1] step = values[2] asc = values[3] is_float = values[4] if limit == Float::INFINITY if step == Float::INFINITY return 1 else return Float::INFINITY end end return Float::INFINITY if step == 0 if is_float # Ported from MRI step_float_size(value, limit, step, asc) else if (asc && value > limit) || (!asc && value < limit) 0 else ((value - limit).abs + 1).fdiv(step.abs).ceil end end end def step_fetch_args(limit, step, to, by) raise ArgumentError, "limit is given twice" if limit && to raise ArgumentError, "step is given twice" if step && by raise ArgumentError, "step cannot be 0" if step == 0 step ||= by || 1 asc = step > 0 limit ||= to || (asc ? Float::INFINITY : -Float::INFINITY) value = @object if value.kind_of? Float or limit.kind_of? Float or step.kind_of? Float return FloatValue(value), FloatValue(limit), FloatValue(step), asc, true else return value, limit, step, asc, false end end end end end