module Comparable ## # call-seq: # obj.clamp(min, max) -> obj # obj.clamp(range) -> obj # # In `(min, max)` form, returns _min_ if _obj_ # `<=>` _min_ is less than zero, _max_ if _obj_ # `<=>` _max_ is greater than zero, and _obj_ # otherwise. # # 12.clamp(0, 100) #=> 12 # 523.clamp(0, 100) #=> 100 # -3.123.clamp(0, 100) #=> 0 # # 'd'.clamp('a', 'f') #=> 'd' # 'z'.clamp('a', 'f') #=> 'f' # # In `(range)` form, returns _range.begin_ if _obj_ # `<=>` _range.begin_ is less than zero, _range.end_ # if _obj_ `<=>` _range.end_ is greater than zero, and # _obj_ otherwise. # # 12.clamp(0..100) #=> 12 # 523.clamp(0..100) #=> 100 # -3.123.clamp(0..100) #=> 0 # # 'd'.clamp('a'..'f') #=> 'd' # 'z'.clamp('a'..'f') #=> 'f' # # If _range.begin_ is `nil`, it is considered smaller than _obj_, # and if _range.end_ is `nil`, it is considered greater than # _obj_. # # -20.clamp(0..) #=> 0 # 523.clamp(..100) #=> 100 # # When _range.end_ is excluded and not `nil`, an exception is # raised. # # 100.clamp(0...100) # ArgumentError # def clamp(min, max=nil) if max.nil? if min.kind_of?(Range) max = min.end if !max.nil? && min.exclude_end? raise ArgumentError, "cannot clamp with an exclusive range" end min = min.begin end end if !min.nil? && !max.nil? cmp = min <=> max if cmp.nil? raise ArgumentError, "comparison of #{min.class} with #{max.class} failed" elsif cmp > 0 raise ArgumentError, "min argument must be smaller than max argument" end end unless min.nil? cmp = self <=> min return self if cmp == 0 return min if cmp < 0 end unless max.nil? cmp = self <=> max return max if cmp > 0 end return self end end