Class: Interval

Inherits:
Object show all
Includes:
EnumerableWithArgs, Multiton::New
Defined in:
lib/carat/interval.rb

Overview

require ‘carat/infinity’

Class Method Summary collapse

Instance Method Summary collapse

Methods included from EnumerableWithArgs

#collect, #detect, #each_slice, #grep, #reject, #select, #sort, #to_a

Methods included from Multiton::New

append_features

Constructor Details

#initialize(first, last, exclude_first = false, exclude_last = false) ⇒ Interval

Returns a new instance of Interval.

Raises:

  • (ArgumentError)


59
60
61
62
63
64
65
66
# File 'lib/carat/interval.rb', line 59

def initialize(first, last, exclude_first=false, exclude_last=false )
  raise ArgumentError, "bad value for interval" if first.class != last.class
  @first = first
  @last = last
  @exclude_first = exclude_first
  @exclude_last = exclude_last
  @direction = (@last <=> @first)
end

Class Method Details

.[](*args) ⇒ Object



55
56
57
# File 'lib/carat/interval.rb', line 55

def self.[]( *args )
  self.new( *args )
end

Instance Method Details

#+@Object

Unary shorthands. These return a new interval exclusive of first, last or both sentinels, repectively.



125
# File 'lib/carat/interval.rb', line 125

def +@ ; Interval.new(first, last, true, false) ; end

#-@Object



126
# File 'lib/carat/interval.rb', line 126

def -@ ; Interval.new(first, last, false, true) ; end

#closedObject

Returns a new interval inclusive of of both sentinels.



105
# File 'lib/carat/interval.rb', line 105

def closed; Interval.new(@first, @last, true, true) ; end

#degenerate?Boolean

Returns true if the start and end sentinels are equal and the interval is closed; otherwise false.

Returns:

  • (Boolean)


91
# File 'lib/carat/interval.rb', line 91

def degenerate? ; @direction == 0 and ! (@exclusive_first or @exclusive_last) ;  end

#directionObject

Returns the direction of the interval indicated by +1, 0 or -1.

(1..5).direction  #=> 1
(5..1).direction  #=> -1
(1..1).direction  #=> 0


102
# File 'lib/carat/interval.rb', line 102

def direction ; @direction ; end

#distanceObject Also known as: length, size

Returns the length of the interval as the difference between the first and last elements. Returns nil if the sentinal objects do not support distance comparison (#distance). TODO: Add n parameter to count segmentations like those produced by #each.



141
142
143
144
145
146
147
148
# File 'lib/carat/interval.rb', line 141

def distance
  @last - @first
  #if @last.respond_to?( :distance )
  #  @last.distance( @first )
  #else
  #  #self.to_a.length
  #end
end

#each(n = 1, d = nil) ⇒ Object Also known as: step

Iterates over the interval, passing each _n_th element to the block. If n is not given then n defaults to 1. Each _n_th step is determined by invoking + or \- n, depending on the direction of the interval. If n is negative the iteration is preformed in reverse form end sentinal to front sentinal. A second parameter, d, can be given in which case the applied step is calculated as a fraction of the interval’s length times n / d. This allows iteration over the whole interval in equal sized segments.

1..5.each { |e| ... }        #=> 1 2 3 4 5
1..5.each(2) { |e| ... }     #=> 1 3 5
1..5.each(1,2) { |e| ... }   #=> 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0


205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/carat/interval.rb', line 205

def each(n=1, d=nil)  # :yield:   
  return (n < 0 ? @last : @first) if degenerate?  # is this right for all values of n ?
  s = d ? self.length.to_f * (n.to_f / d.to_f) : n.abs
  raise "Cannot iterate over zero length steps." if s == 0
  s = s * @direction
  if n < 0
    e = @exclude_last ? @last - s : @last
    #e = @exclude_last ? @last.pred(s) : @last
    t = @exlude_last ? 1 : 0
    #while e.cmp(@first) >= t
    while (e <=> @first) >= t
      yield(e)
      e -= s
      #e = e.pred(s)
    end
  else
    e = @exclude_first ? @first + s : @first
    #e = @exclude_first ? @first.succ(s) : @first
    t = @exlude_last ? -1 : 0
    #while e.cmp(@last) <= t
    while (e <=> @last) <= t
      yield(e)
      e += s
      #e = e.succ(s)
    end
  end
end

#eql?(other) ⇒ Boolean

Compares two intervals to see if they are equal

Returns:

  • (Boolean)


240
241
242
243
244
245
246
# File 'lib/carat/interval.rb', line 240

def eql?(other)
  return false unless @first == other.first
  return false unless @last == other.last
  return false unless @exclude_first == other.exclude_first?
  return false unless @exclude_last == other.exclude_last?
  true
end

#exclude_first?Boolean Also known as: exclude_begin?

Returns:

  • (Boolean)


81
# File 'lib/carat/interval.rb', line 81

def exclude_first? ; @exclude_first ; end

#exclude_last?Boolean Also known as: exclude_end?

Returns:

  • (Boolean)


82
# File 'lib/carat/interval.rb', line 82

def exclude_last? ; @exclude_last ; end

#firstObject Also known as: begin

Returns the first or last sentinal of the interval.



77
# File 'lib/carat/interval.rb', line 77

def first ; @first ; end

#first_closedObject

Returns a new interval with one of the two sentinels opened or closed



118
# File 'lib/carat/interval.rb', line 118

def first_closed ; Interval.new(@first, @last, false, true) ; end

#first_openedObject



120
# File 'lib/carat/interval.rb', line 120

def first_opened ; Interval.new(@first, @last, true, false) ; end

#half_closed(e = false) ⇒ Object

Returns a new interval with either the first or the last sentinel exclusive. If the parameter is false, the deafult, then the first sentinel is excluded; if the parameter is true, the last sentinel is excluded.



113
114
115
# File 'lib/carat/interval.rb', line 113

def half_closed(e=false)
  e ? Interval.new(@first, @last, true, false) : Interval.new(@first, @last, false, true)
end

#include?(x) ⇒ Boolean Also known as: ===, member?

Returns true or false if the element is part of the interval.

Returns:

  • (Boolean)


163
164
165
166
167
168
# File 'lib/carat/interval.rb', line 163

def include?(x)
  # todo: infinity?   
  tf = exclude_first? ? 1 : 0
  tl = exclude_last? ? -1 : 0
  (x <=> first) >= tf and (x <=> last) <= tl
end

#lastObject Also known as: end



78
# File 'lib/carat/interval.rb', line 78

def last ; @last ; end

#last_closedObject



119
# File 'lib/carat/interval.rb', line 119

def last_closed ; Interval.new(@first, @last, true, false) ; end

#last_openedObject



121
# File 'lib/carat/interval.rb', line 121

def last_opened ; Interval.new(@first, @last, false, true) ; end

#maxObject

Returns the greater of the first and last sentinals.



158
159
160
# File 'lib/carat/interval.rb', line 158

def max
  ((@first <=> @last) == 1) ? @first : @last
end

#minObject

Returns the lesser of the first and last sentinals.



153
154
155
# File 'lib/carat/interval.rb', line 153

def min
  ((@first <=> @last) == -1) ? @first : @last
end

#null?Boolean

Returns true if the start and end sentinels are equal and the interval is open; otherwise false.

Returns:

  • (Boolean)


94
# File 'lib/carat/interval.rb', line 94

def null? ; @direction == 0 and @exclusive_first and @exclusive_last ; end

#openedObject

Returns a new interval exclusive of both sentinels.



108
# File 'lib/carat/interval.rb', line 108

def opened; Interval.new(@first, @last, true, true) ; end

#reversedObject

Returns a new interval with the sentinels reversed.

(0..10).reversed  #=> 10..0


133
134
135
# File 'lib/carat/interval.rb', line 133

def reversed
  Interval.new(@last, @first, true, true)
end

#sentinelsObject

Returns a two element array of first and last sentinels.

(0..10).sentinels   #=> [0,10]


72
73
74
# File 'lib/carat/interval.rb', line 72

def sentinels
  return [@first, @last]
end

#~@Object



127
# File 'lib/carat/interval.rb', line 127

def ~@ ; Interval.new(first, last, true, true) ; end