File: dense_int_array.rb

package info (click to toggle)
ruby-bio 2.0.6-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,108 kB
  • sloc: ruby: 68,331; perl: 13; makefile: 11; sh: 1
file content (198 lines) | stat: -rw-r--r-- 4,366 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#
# bio/util/restriction_enzyme/dense_int_array.rb - Internal data storage for Bio::RestrictionEnzyme::Range::SequenceRange
#
# Copyright::   Copyright (C) 2011
#               Naohisa Goto <ng@bioruby.org>
#               Tomoaki NISHIYAMA
# License::     The Ruby License
#

module Bio

require 'bio/util/restriction_enzyme' unless const_defined?(:RestrictionEnzyme)

class RestrictionEnzyme

  # a class to store integer numbers, containing many contiguous
  # integral numbers.
  #
  # Bio::RestrictionEnzyme internal use only.
  # Please do not create the instance outside Bio::RestrictionEnzyme.
  class DenseIntArray
    MutableRange = Struct.new(:first, :last)

    include Enumerable

    # Same usage as Array.[]
    def self.[](*args)
      a = self.new
      args.each do |elem|
        a.push elem
      end
      a
    end

    # creates a new object
    def initialize
      @data = []
    end

    # initialize copy
    def initialize_copy(other)
      super(other)
      @data = @data.collect { |elem| elem.dup }
    end

    # sets internal data object
    def internal_data=(a)
      #clear_cache
      @data = a
      self
    end
    protected :internal_data=

    # gets internal data object
    def internal_data
      @data
    end
    protected :internal_data

    # Same usage as Array#[]
    def [](*arg)
      #$stderr.puts "SortedIntArray#[]"
      to_a[*arg]
    end

    # Not implemented
    def []=(*arg)
      raise NotImplementedError, 'DenseIntArray#[]= is not implemented.'
    end

    # Same usage as Array#each
    def each
      @data.each do |elem|
        elem.first.upto(elem.last) { |num| yield num }
      end
      self
    end

    # Same usage as Array#reverse_each
    def reverse_each
      @data.reverse_each do |elem|
        elem.last.downto(elem.first) { |num| yield num }
      end
      self
    end

    # Same usage as Array#+, but accepts only the same classes instance.
    def +(other)
      unless other.is_a?(self.class) then
        raise TypeError, 'unsupported data type'
      end
      tmpdata = @data + other.internal_data
      tmpdata.sort! { |a,b| a.first <=> b.first }
      result = self.class.new
      return result if tmpdata.empty?
      newdata = result.internal_data
      newdata.push tmpdata[0].dup
      (1...(tmpdata.size)).each do |i|
        if (x = newdata[-1].last) >= tmpdata[i].first then
          newdata[-1].last = tmpdata[i].last if tmpdata[i].last > x
        else
          newdata.push tmpdata[i].dup
        end
      end
      result
    end

    # Same usage as Array#==
    def ==(other)
      if r = super(other) then
        r
      elsif other.is_a?(self.class) then
        other.internal_data == @data
      else
        false
      end
    end

    # Same usage as Array#concat
    def concat(ary)
      ary.each { |elem| self.<<(elem) }
      self
    end

    # Same usage as Array#push
    def push(*args)
      args.each do |elem|
        self.<<(elem)
      end
      self
    end

    # Same usage as Array#unshift
    def unshift(*arg)
      raise NotImplementedError, 'DenseIntArray#unshift is not implemented.'
    end

    # Same usage as Array#<<
    def <<(elem)
      if !@data.empty? and
          @data[-1].last + 1 == elem then
        @data[-1].last = elem
      else
        @data << MutableRange.new(elem, elem)
      end
      self
    end

    # Same usage as Array#include?
    def include?(elem)
      return false if @data.empty? or elem < self.first or self.last < elem
      @data.any? do |range|
        range.first <= elem && elem <= range.last
      end
    end

    # Same usage as Array#first
    def first
      elem = @data.first
      elem ? elem.first : nil
    end

    # Same usage as Array#last
    def last
      elem = @data.last
      elem ? elem.last : nil
    end

    # Same usage as Array#size
    def size
      sum = 0
      @data.each do |range|
        sum += (range.last - range.first + 1)
      end
      sum
    end
    alias length size

    # Same usage as Array#delete
    def delete(elem)
      raise NotImplementedError, 'DenseIntArray#delete is not implemented.'
    end

    # Does nothing
    def sort!(&block)
      # does nothing
      self
    end

    # Does nothing
    def uniq!
      # does nothing
      self
    end
  end #class DenseIntArray

end #class RestrictionEnzyme
end #module Bio