Infinity = 1.0/0
# for added flare
module Comparable
alias old_between? between?
def between?(a,b=nil)
if a.kind_of?(Range)
a.circumscribes?(self)
else
old_between(a,b)
end
end
end
class Range
alias init_old initialize
def initialize(first, last, exfirst=false, exlast=false, step=1)
@exclude_first = exfirst
@step = step
init_old(first, last, exlast)
# not needed, Ruby catches already
# if ! numeric_range? && first == -Infinity
# raise "Ordinal range can not begin with -Infinity."
# end
end
def exclude_first?
@exclude_first
end
alias exclude_begin? exclude_first?
alias exclude_last? exclude_end?
def numeric_range?
@numeric_range ||= (first.kind_of?(Numeric) && last.kind_of?(Numeric))
end
def infinite_range?
@infinite_range ||= (first.abs == Infinity or last.abs == Infinity)
end
def step(s=nil)
if s
@step = s
else
@step ||= 1
end
@step
end
def x(s)
@step = s
self
end
def member?(val)
if numeric_range?
return false if ! circumscribes?(val)
return true if first == -Infinity && last == Infinity # ?
return true if val.abs == Infinity # this one was tricky
if first.abs != Infinity
return (((val + first) % step) == 0)
elsif first == -Infinity # flip this around
r = Range.new(-last,Infinity,exclude_last?,exclude_first?,step)
return r.member?(-val)
else # first == Infinity
true
end
else # ordinal range
# looks like this isn't needed as Ruby sees this a bad news already!
# # last can't be Infinite too (otherwise it be numeric range)
# if first == -Infinity
# # should be caught in initialize but I can't trap literal so...
# raise "Ordinal range can not begin with -Infinity."
# end
# basic operation
til = exclude_last? ? -1 : 0
elem = exclude_first? ? first.succ : first
while (elem <=> last) < til
return true if (val <=> elem) == 0
step.times { elem = elem.succ }
end
end
false
end
alias include? member?
def circumscribes?(val)
case val<=>first
when -1 then return false
when 0 then return false if exclude_first?
end
case val<=>last
when 1 then return false
when 0 then return false if exclude_last?
end
return true
end
end
-------------------
# no doubt there are a lot more tests to do
require 'succ.succ/range'
require 'test/unit'
class GeneralTest < Test::Unit::TestCase
def test_circumscribes?
a = (1..10)
assert_equal(false, a.circumscribes?(0))
assert_equal(true, a.circumscribes?(1))
assert_equal(true, a.circumscribes?(2))
assert_equal(true, a.circumscribes?(9))
assert_equal(true, a.circumscribes?(10))
assert_equal(false, a.circumscribes?(11))
a = (1...10)
assert_equal(false, a.circumscribes?(0))
assert_equal(true, a.circumscribes?(1))
assert_equal(true, a.circumscribes?(2))
assert_equal(true, a.circumscribes?(9))
assert_equal(false, a.circumscribes?(10))
assert_equal(false, a.circumscribes?(11))
a = Range.new(1,10,true,false)
assert_equal(false, a.circumscribes?(0))
assert_equal(false, a.circumscribes?(1))
assert_equal(true, a.circumscribes?(2))
assert_equal(true, a.circumscribes?(9))
assert_equal(true, a.circumscribes?(10))
assert_equal(false, a.circumscribes?(11))
a = Range.new(1,10,true,true)
assert_equal(false, a.circumscribes?(0))
assert_equal(false, a.circumscribes?(1))
assert_equal(true, a.circumscribes?(2))
assert_equal(true, a.circumscribes?(9))
assert_equal(false, a.circumscribes?(10))
assert_equal(false, a.circumscribes?(11))
end
end
class LrgNumericTest < Test::Unit::TestCase
def test_include
a = (0...100000000)
assert_equal(true, a.include?(0))
assert_equal(true, a.include?(1000))
assert_equal(true, a.include?(1000000))
assert_equal(false, a.include?(100000000))
assert_equal(false, a.include?(Infinity))
end
def test_include_with_step
a = (0..100000000).x 5
assert_equal(true, a.include?(0))
assert_equal(true, a.include?(5))
assert_equal(false, a.include?(70007))
assert_equal(true, a.include?(5000005))
assert_equal(false, a.include?(Infinity))
end
end
class InfTest < Test::Unit::TestCase
def test_include?
a = (-Infinity..-3)
assert_equal(true, a.include?(-Infinity))
assert_equal(true, a.include?(-4))
assert_equal(true, a.include?(-3))
assert_equal(false, a.include?(-2))
assert_equal(false, a.include?(Infinity))
a = (-Infinity...-3)
assert_equal(true, a.include?(-Infinity))
assert_equal(true, a.include?(-4))
assert_equal(false, a.include?(-3))
assert_equal(false, a.include?(-2))
assert_equal(false, a.include?(Infinity))
a = (-3..Infinity)
assert_equal(false, a.include?(-Infinity))
assert_equal(false, a.include?(-4))
assert_equal(true, a.include?(-3))
assert_equal(true, a.include?(-2))
assert_equal(true, a.include?(Infinity))
a = (-Infinity..Infinity)
assert_equal(true, a.include?(-Infinity))
assert_equal(true, a.include?(-4))
assert_equal(true, a.include?(-3))
assert_equal(true, a.include?(-2))
assert_equal(true, a.include?(Infinity))
a = (-3..-2)
assert_equal(false, a.include?(-Infinity))
assert_equal(false, a.include?(-4))
assert_equal(true, a.include?(-3))
assert_equal(true, a.include?(-2))
assert_equal(false, a.include?(Infinity))
end
end
class OrdinalTest < Test::Unit::TestCase
def test_include
a = ('a'..'g')
assert_equal(false, a.include?(-Infinity))
assert_equal(true, a.include?('a'))
assert_equal(true, a.include?('c'))
assert_equal(false, a.include?('z'))
assert_equal(false, a.include?(Infinity))
end
def test_error
assert_raises(ArgumentError) {
a = (-Infinity..'z')
}
end
end
--------------------
Loaded suite range_test
Started
......
Finished in 0.024425 seconds.
6 tests, 65 assertions, 0 failures, 0 errors