Class: Ibex::Tables::Compact

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/tables/compact.rb

Overview

Sparse table represented by per-row offsets and ownership checks.

Direct Known Subclasses

CompactActions

Constant Summary collapse

DENSE_CELL_LIMIT =

: Integer

1_000_000

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(offsets:, values:, checks:, row_count:, dense_width: nil) ⇒ Compact

Returns a new instance of Compact.



126
127
128
129
130
131
132
133
134
# File 'lib/ibex/tables/compact.rb', line 126

def initialize(offsets:, values:, checks:, row_count:, dense_width: nil)
  @offsets = offsets.freeze
  @values = values.freeze
  @checks = checks.freeze
  @row_count = row_count
  @dense_width = dense_width
  @dense_values = dense_layout(dense_width)
  freeze
end

Instance Attribute Details

#checksObject (readonly)

: Array



69
70
71
# File 'lib/ibex/tables/compact.rb', line 69

def checks
  @checks
end

#dense_valuesObject (readonly)

: Array?



71
72
73
# File 'lib/ibex/tables/compact.rb', line 71

def dense_values
  @dense_values
end

#dense_widthObject (readonly)

: Integer?



72
73
74
# File 'lib/ibex/tables/compact.rb', line 72

def dense_width
  @dense_width
end

#offsetsObject (readonly)

: Array



67
68
69
# File 'lib/ibex/tables/compact.rb', line 67

def offsets
  @offsets
end

#row_countObject (readonly)

: Integer



70
71
72
# File 'lib/ibex/tables/compact.rb', line 70

def row_count
  @row_count
end

#valuesObject (readonly)

: Array



68
69
70
# File 'lib/ibex/tables/compact.rb', line 68

def values
  @values
end

Class Method Details

.build(rows, dense: true) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/ibex/tables/compact.rb', line 76

def build(rows, dense: true)
  offsets = Array.new(rows.length, 0)
  values = [] #: Array[untyped]
  checks = [] #: Array[Integer?]
  next_offsets = {} #: Hash[Array[Integer], Integer]
  rows.each_index.sort_by { |row| [-rows[row].length, row] }.each do |row|
    offset = find_offset(rows[row].keys, checks, next_offsets)
    offsets[row] = offset
    rows[row].each do |column, value|
      index = offset + column
      values[index] = value
      checks[index] = row
    end
  end
  dense_width = rows.flat_map(&:keys).max.to_i + 1 if dense
  dense_width = nil if dense_width && (rows.length * dense_width) > DENSE_CELL_LIMIT
  new(
    offsets: offsets, values: values, checks: checks, row_count: rows.length,
    dense_width: dense_width
  )
end

.packed(offsets, values, checks, row_count:, dense_width: nil) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/ibex/tables/compact.rb', line 100

def packed(offsets, values, checks, row_count:, dense_width: nil)
  new(
    offsets: PackedIntegers.decode_required(offsets),
    values: PackedIntegers.decode(values),
    checks: PackedIntegers.decode(checks),
    row_count: row_count,
    dense_width: dense_width
  )
end

Instance Method Details

#lookup(row, column) ⇒ Object

Keep predicate dispatch out of this lookup because every parser action and goto crosses it. rubocop:disable Style/NumericPredicate



140
141
142
143
144
145
146
147
# File 'lib/ibex/tables/compact.rb', line 140

def lookup(row, column)
  return nil if row < 0 || row >= @row_count || column < 0

  index = @offsets[row] + column
  return nil if index < 0 || index >= @checks.length

  @checks[index] == row ? @values[index] : nil
end

#row(row) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/ibex/tables/compact.rb', line 151

def row(row)
  return {} unless row.between?(0, @row_count - 1)

  result = {} #: Hash[Integer, untyped]
  @checks.each_index do |index|
    next unless @checks[index] == row

    result[index - @offsets[row]] = @values[index]
  end
  result
end