Class: Interval

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

Overview

require ‘mega/infinity’

Constant Summary

Constants included from EnumerableArgs

EnumerableArgs::VERSION

Class Method Summary collapse

Instance Method Summary collapse

Methods included from EnumerableArgs

#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)


77
78
79
80
81
82
83
84
# File 'lib/mega/interval.rb', line 77

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



73
74
75
# File 'lib/mega/interval.rb', line 73

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.



143
# File 'lib/mega/interval.rb', line 143

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

#-@Object



144
# File 'lib/mega/interval.rb', line 144

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

#closedObject

Returns a new interval inclusive of of both sentinels.



123
# File 'lib/mega/interval.rb', line 123

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)


109
# File 'lib/mega/interval.rb', line 109

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


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

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.



159
160
161
162
163
164
165
166
# File 'lib/mega/interval.rb', line 159

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


223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/mega/interval.rb', line 223

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)


258
259
260
261
262
263
264
# File 'lib/mega/interval.rb', line 258

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)


99
# File 'lib/mega/interval.rb', line 99

def exclude_first? ; @exclude_first ; end

#exclude_last?Boolean Also known as: exclude_end?

Returns:

  • (Boolean)


100
# File 'lib/mega/interval.rb', line 100

def exclude_last? ; @exclude_last ; end

#firstObject Also known as: begin

Returns the first or last sentinal of the interval.



95
# File 'lib/mega/interval.rb', line 95

def first ; @first ; end

#first_closedObject

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



136
# File 'lib/mega/interval.rb', line 136

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

#first_openedObject



138
# File 'lib/mega/interval.rb', line 138

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.



131
132
133
# File 'lib/mega/interval.rb', line 131

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)


181
182
183
184
185
186
# File 'lib/mega/interval.rb', line 181

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



96
# File 'lib/mega/interval.rb', line 96

def last ; @last ; end

#last_closedObject



137
# File 'lib/mega/interval.rb', line 137

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

#last_openedObject



139
# File 'lib/mega/interval.rb', line 139

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

#maxObject

Returns the greater of the first and last sentinals.



176
177
178
# File 'lib/mega/interval.rb', line 176

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

#minObject

Returns the lesser of the first and last sentinals.



171
172
173
# File 'lib/mega/interval.rb', line 171

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)


112
# File 'lib/mega/interval.rb', line 112

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

#openedObject

Returns a new interval exclusive of both sentinels.



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

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

#reversedObject

Returns a new interval with the sentinels reversed.

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


151
152
153
# File 'lib/mega/interval.rb', line 151

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]


90
91
92
# File 'lib/mega/interval.rb', line 90

def sentinels
  return [@first, @last]
end

#~@Object



145
# File 'lib/mega/interval.rb', line 145

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