Commit 4085709a authored by Ryan Lopopolo's avatar Ryan Lopopolo

Specialize Enumerable#max and Enumerable#min for Range

This patch prevents a hang for pathalogical (large) Ranges when
computing max and min.

Range inherits its implementation of max and min from Enumerable.
Enumerable implements max and min by calling each. For Range objects,
this is unnecessary since we know the max and the min by the end and
begin attributes.

It is also very slow. This code hangs unnecessarily:

    (0..2**32).max
    # ... hang
    (0..2**32).min
    # ... hang

This patch overrides max and min after including enumerable to yield
based on the begin and end methods.
parent 469c6261
......@@ -15,7 +15,8 @@ class Range
val = self.first
last = self.last
if val.kind_of?(Fixnum) && last.kind_of?(Fixnum) # fixnums are special
# numerics are special
if (val.kind_of?(Fixnum) || val.kind_of?(Float)) && (last.kind_of?(Fixnum) || last.kind_of?(Float))
lim = last
lim += 1 unless exclude_end?
i = val
......@@ -64,4 +65,67 @@ end
# ISO 15.2.14.3
class Range
include Enumerable
def max(&block)
val = self.first
last = self.last
# numerics are special
if (val.kind_of?(Fixnum) || val.kind_of?(Float)) && (last.kind_of?(Fixnum) || last.kind_of?(Float))
return nil if val > last
return nil if val == last && exclude_end?
max = last
max -= 1 if exclude_end?
max = val if block && block.call(val, last) > 0
return max
end
max = nil
each do |item|
max =
if max.nil?
item
elsif block && block.call(max, item) > 0
item
elsif item > max
item
else
max
end
end
max
end
def min(&block)
val = self.first
last = self.last
# numerics are special
if (val.kind_of?(Fixnum) || val.kind_of?(Float)) && (last.kind_of?(Fixnum) || last.kind_of?(Float))
return nil if val > last
return nil if val == last && exclude_end?
min = val
if block && block.call(val, last) > 0
min = last
min -= 1 if exclude_end?
end
return min
end
min = nil
each do |item|
min =
if min.nil?
item
elsif block && block.call(min, item) < 0
item
elsif item < min
item
else
min
end
end
min
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment