Tighten std/bzip2 Huffman leaf node bit packing
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 735217b..717414f 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -25849,11 +25849,11 @@
label__2__break:;
v_node_index = v_stack_values[(v_stack_height - 1)];
if (v_symbol_index < 2) {
- v_leaf_value = ((uint16_t)((1280 + v_symbol_index)));
+ v_leaf_value = ((uint16_t)((769 + v_symbol_index)));
} else if ((v_symbol_index + 1) < self->private_impl.f_num_symbols) {
- v_leaf_value = ((uint16_t)((1023 + v_symbol_index)));
+ v_leaf_value = ((uint16_t)((511 + v_symbol_index)));
} else {
- v_leaf_value = 2047;
+ v_leaf_value = 768;
}
if (self->private_data.f_huffman_trees[a_which][v_node_index][0] == 0) {
self->private_data.f_huffman_trees[a_which][v_node_index][0] = v_leaf_value;
@@ -26200,7 +26200,7 @@
v_table_entry = self->private_data.f_huffman_tables[v_which][(v_bits >> 24)];
v_bits <<= (v_table_entry >> 12);
v_n_bits -= ((uint32_t)((v_table_entry >> 12)));
- v_child = (v_table_entry & 2047);
+ v_child = (v_table_entry & 1023);
while (v_child < 257) {
v_child = self->private_data.f_huffman_trees[v_which][v_child][(v_bits >> 31)];
v_bits <<= 1;
@@ -26210,7 +26210,7 @@
}
v_n_bits -= 1;
}
- if (v_child < 1280) {
+ if (v_child < 768) {
v_child_ff = ((uint32_t)((v_child & 255)));
v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff]));
wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1 + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff));
@@ -26224,7 +26224,7 @@
v_block_size += 1;
v_run_shift = 0;
goto label__outer__continue;
- } else if (v_child > 1281) {
+ } else if (v_child == 768) {
self->private_impl.f_decode_huffman_finished = true;
goto label__outer__break;
}
@@ -26232,7 +26232,7 @@
status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
goto exit;
}
- v_run = (((uint32_t)((v_child - 1279))) << v_run_shift);
+ v_run = ((((uint32_t)(v_child)) & 3) << v_run_shift);
v_run_shift += 1;
v_i = v_block_size;
v_j = (v_run + v_block_size);
@@ -26339,7 +26339,7 @@
if (v_child < 257) {
v_node_index = ((uint32_t)(v_child));
goto label__0__continue;
- } else if (v_child < 1280) {
+ } else if (v_child < 768) {
v_child_ff = ((uint32_t)((v_child & 255)));
v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff]));
wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1 + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff));
@@ -26353,7 +26353,7 @@
self->private_impl.f_block_size += 1;
self->private_impl.f_decode_huffman_run_shift = 0;
goto label__0__break;
- } else if (v_child > 1281) {
+ } else if (v_child == 768) {
self->private_impl.f_decode_huffman_finished = true;
goto label__outer__break;
}
@@ -26361,7 +26361,7 @@
status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
goto exit;
}
- v_run = (((uint32_t)((v_child - 1279))) << self->private_impl.f_decode_huffman_run_shift);
+ v_run = ((((uint32_t)(v_child)) & 3) << self->private_impl.f_decode_huffman_run_shift);
self->private_impl.f_decode_huffman_run_shift += 1;
v_i = self->private_impl.f_block_size;
v_j = (v_run + self->private_impl.f_block_size);
diff --git a/std/bzip2/decode_bzip2.wuffs b/std/bzip2/decode_bzip2.wuffs
index ee34906..19f670f 100644
--- a/std/bzip2/decode_bzip2.wuffs
+++ b/std/bzip2/decode_bzip2.wuffs
@@ -91,11 +91,11 @@
// huffman_tables[which] caches the result of walking huffman_trees[which]
// for each possible 8-bit input. The base.u16 value decomposes as:
- // - The low 11 bits are the final node, where finality comes either from
+ // - The low 10 bits are the final node, where finality comes either from
// hitting a leaf node or from spending all 8 bits of the input. As per
- // the build_huffman_tree method, a value of 0x3FF = 1023 or less means
- // a branch node and 0x400 = 1024 or more means a leaf node.
- // - The middle bit is unused.
+ // the build_huffman_tree method, a value of 0x100 = 256 or less means
+ // a branch node and 0x201 = 513 or more means a leaf node.
+ // - The middle 2 bits are unused.
// - The high 4 bits are the number of input bits spent.
huffman_tables : array[6] array[256] base.u16,
@@ -544,31 +544,31 @@
// build_huffman_tree builds a canonical Huffman tree given the symbols' code
// lengths. For the "abraca.txt.bz2" example, the code lengths are:
-// - symbol=0x500 (RUNA) cl=3
-// - symbol=0x501 (RUNB) cl=3
-// - symbol=0x401 (m01) cl=2
-// - symbol=0x402 (m02) cl=3
-// - symbol=0x403 (m03) cl=2
-// - symbol=0x7FF (EOB) cl=3
+// - symbol=0x301 (RUNA) cl=3
+// - symbol=0x302 (RUNB) cl=3
+// - symbol=0x201 (m01) cl=2
+// - symbol=0x202 (m02) cl=3
+// - symbol=0x203 (m03) cl=2
+// - symbol=0x300 (EOB) cl=3
//
// The bitstring mapping is:
-// - "00" 0x401 (m01)
-// - "01" 0x403 (m03)
-// - "100" 0x500 (RUNA)
-// - "101" 0x501 (RUNB)
-// - "110" 0x402 (m02)
-// - "111" 0x7FF (EOB)
+// - "00" 0x201 (m01)
+// - "01" 0x203 (m03)
+// - "100" 0x301 (RUNA)
+// - "101" 0x302 (RUNB)
+// - "110" 0x202 (m02)
+// - "111" 0x300 (EOB)
//
// The Huffman tree has 5 branch nodes (where 5+1 is both the number of leaf
// nodes and the number of symbols). Each branch node has two children,
-// represented by a base.u16 value. 256 = 0x100 or less means that the child is
-// a branch node. 1024 = 0x400 or above means a leaf node (with the symbol
-// values as above).
+// represented by a base.u16 value. 0x100 = 256 or less means that the child is
+// a branch node. 0x201 ..= 0x2FF means an mNN leaf node. 0x300, 0x301 and
+// 0x302 mean EOB, RUNA and RUNB leaf nodes.
// - node0 = [0x001 (node1), 0x002 (node2)]
-// - node1 = [0x401 (m01) , 0x403 (m03) ]
+// - node1 = [0x201 (m01) , 0x203 (m03) ]
// - node2 = [0x003 (node3), 0x004 (node4)]
-// - node3 = [0x500 (RUNA) , 0x501 (RUNB) ]
-// - node4 = [0x402 (m02) , 0x7FF (EOB) ]
+// - node3 = [0x301 (RUNA) , 0x302 (RUNB) ]
+// - node4 = [0x202 (m02) , 0x300 (EOB) ]
//
// For example, the tree walk from node0 right (1) to node2 left (0) to node3
// left (0) to RUNA means that the RUNA bitstring is "100".
@@ -577,12 +577,12 @@
// length order, maintaining a stack of nodes that's the path from the root
// (node0) to the latest created-but-unfinished node. Created means that their
// left child is assigned (non-zero). Unfinished means that their right child
-// is pending (zero). For example, after adding the 0x401, 0x403 and 0x500
+// is pending (zero). For example, after adding the 0x201, 0x203 and 0x301
// symbols, we would have this (in-progress) tree:
// - node0 = [0x001 (node1), 0x002 (node2)]
-// - node1 = [0x401 (m01) , 0x403 (m03) ]
+// - node1 = [0x201 (m01) , 0x203 (m03) ]
// - node2 = [0x003 (node3), 0 ]
-// - node3 = [0x500 (RUNA) , 0 ]
+// - node3 = [0x301 (RUNA) , 0 ]
//
// The stack would be [node0, node2, node3]. The next symbol would fill in the
// top of the stack, node3. If that symbol's code length matches the stack
@@ -650,11 +650,11 @@
node_index = stack_values[stack_height - 1]
if symbol_index < 2 {
- leaf_value = (0x500 + symbol_index) as base.u16
+ leaf_value = (0x301 + symbol_index) as base.u16
} else if (symbol_index + 1) < this.num_symbols {
- leaf_value = (0x3FF + symbol_index) as base.u16
+ leaf_value = (0x1FF + symbol_index) as base.u16
} else {
- leaf_value = 0x7FF
+ leaf_value = 0x300
}
if this.huffman_trees[args.which][node_index][0] == 0 {
diff --git a/std/bzip2/decode_huffman_fast.wuffs b/std/bzip2/decode_huffman_fast.wuffs
index 05e5b8c..eb404d0 100644
--- a/std/bzip2/decode_huffman_fast.wuffs
+++ b/std/bzip2/decode_huffman_fast.wuffs
@@ -27,7 +27,7 @@
var i : base.u32
var j : base.u32
var output : base.u32[..= 255]
- var run : base.u32[..= 16_777216] // 16_777216 = (2 << 23)
+ var run : base.u32[..= 12_582912] // 12_582912 = (3 << 22)
var mtft0 : base.u32[..= 255]
bits = this.bits
@@ -58,7 +58,7 @@
table_entry = this.huffman_tables[which][bits >> 24]
bits ~mod<<= table_entry >> 12
n_bits -= (table_entry >> 12) as base.u32
- child = table_entry & 0x7FF
+ child = table_entry & 0x3FF
while child < 257 {
child = this.huffman_trees[which][child][bits >> 31]
bits ~mod<<= 1
@@ -68,7 +68,7 @@
n_bits -= 1
} endwhile
- if child < 1280 { // mNN symbol.
+ if child < 0x300 { // mNN symbol.
// Move to front.
child_ff = (child & 0xFF) as base.u32
output = this.mtft[child_ff] as base.u32
@@ -85,7 +85,7 @@
block_size += 1
run_shift = 0
continue.outer
- } else if child > 1281 { // EOB symbol.
+ } else if child == 0x300 { // EOB symbol.
this.decode_huffman_finished = true
break.outer
}
@@ -94,7 +94,7 @@
if run_shift >= 23 {
return "#bad block length"
}
- run = ((child - 1279) as base.u32) << run_shift
+ run = ((child as base.u32) & 3) << run_shift
run_shift += 1
i = block_size
j = run + block_size
diff --git a/std/bzip2/decode_huffman_slow.wuffs b/std/bzip2/decode_huffman_slow.wuffs
index 5c41a83..035f0c8 100644
--- a/std/bzip2/decode_huffman_slow.wuffs
+++ b/std/bzip2/decode_huffman_slow.wuffs
@@ -21,7 +21,7 @@
var i : base.u32
var j : base.u32
var output : base.u32[..= 255]
- var run : base.u32[..= 16_777216] // 16_777216 = (2 << 23)
+ var run : base.u32[..= 12_582912] // 12_582912 = (3 << 22)
var mtft0 : base.u32[..= 255]
// Apply the Huffman trees.
@@ -53,7 +53,7 @@
node_index = child as base.u32
continue
- } else if child < 1280 { // mNN symbol.
+ } else if child < 0x300 { // mNN symbol.
// Move to front.
child_ff = (child & 0xFF) as base.u32
output = this.mtft[child_ff] as base.u32
@@ -71,7 +71,7 @@
this.decode_huffman_run_shift = 0
break
- } else if child > 1281 { // EOB symbol.
+ } else if child == 0x300 { // EOB symbol.
this.decode_huffman_finished = true
break.outer
}
@@ -80,7 +80,7 @@
if this.decode_huffman_run_shift >= 23 {
return "#bad block length"
}
- run = ((child - 1279) as base.u32) << this.decode_huffman_run_shift
+ run = ((child as base.u32) & 3) << this.decode_huffman_run_shift
this.decode_huffman_run_shift += 1
i = this.block_size
j = run + this.block_size