Class: JXL::Modular::MATree

Inherits:
Object
  • Object
show all
Defined in:
lib/jxl/modular/ma_tree.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nodes, leaf_count) ⇒ MATree

Returns a new instance of MATree.



12
13
14
15
# File 'lib/jxl/modular/ma_tree.rb', line 12

def initialize(nodes, leaf_count)
  @nodes = nodes
  @leaf_count = leaf_count
end

Instance Attribute Details

#leaf_countObject (readonly)

Returns the value of attribute leaf_count.



10
11
12
# File 'lib/jxl/modular/ma_tree.rb', line 10

def leaf_count
  @leaf_count
end

#nodesObject (readonly)

Returns the value of attribute nodes.



10
11
12
# File 'lib/jxl/modular/ma_tree.rb', line 10

def nodes
  @nodes
end

Class Method Details

.read(reader, max_nodes: 1 << 20) ⇒ Object



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
# File 'lib/jxl/modular/ma_tree.rb', line 17

def self.read(reader, max_nodes: 1 << 20)
  decoder = Entropy::Decoder.read(reader, 6)
  nodes = []
  leaves = 0
  pending = 1
  while pending.positive?
    raise ResourceLimitError, "MA tree is too large" if nodes.length >= max_nodes

    pending -= 1
    property = decoder.read_uint(1) - 1
    raise CorruptError, "invalid MA tree property" unless property.between?(-1, 255)

    if property == -1
      nodes << read_leaf(decoder, leaves)
      leaves += 1
    else
      split = Num.unpack_signed(decoder.read_uint(0))
      left = nodes.length + pending + 1
      nodes << MANode.new(property:, split_value: split, left:, right: left + 1,
                          predictor: nil, offset: nil, multiplier: nil, context: nil)
      pending += 2
    end
  end
  decoder.final_state!
  validate!(nodes)
  new(nodes, leaves)
end

Instance Method Details

#inspect_treeObject



55
56
57
58
59
60
61
62
63
# File 'lib/jxl/modular/ma_tree.rb', line 55

def inspect_tree
  nodes.each_with_index.map do |node, index|
    if node.leaf?
      "#{index}: leaf ctx=#{node.context} pred=#{node.predictor} offset=#{node.offset} mul=#{node.multiplier}"
    else
      "#{index}: p#{node.property}>#{node.split_value} ? #{node.left} : #{node.right}"
    end
  end.join("\n")
end

#leaf(properties) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/jxl/modular/ma_tree.rb', line 45

def leaf(properties)
  index = 0
  loop do
    node = nodes.fetch(index)
    return node if node.leaf?

    index = (properties[node.property] || 0) > node.split_value ? node.left : node.right
  end
end

#weighted?Boolean

Returns:

  • (Boolean)


65
# File 'lib/jxl/modular/ma_tree.rb', line 65

def weighted? = nodes.any? { _1.property == 15 || _1.predictor == 6 }