]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Reorder functions related to build_tree to more closely match order of
authorHans Kristian Rosbach <hk-git@circlestorm.org>
Mon, 18 Aug 2025 19:25:29 +0000 (21:25 +0200)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Wed, 20 Aug 2025 11:51:48 +0000 (13:51 +0200)
actual usage in the code. Could also help with cache locality.

trees.c

diff --git a/trees.c b/trees.c
index f111aa949453b3c14e304b65bdd19bfc8d7e92cb..e90488b6471408130268a5f5b27a04a9e6cb878c 100644 (file)
--- a/trees.c
+++ b/trees.c
@@ -67,8 +67,8 @@ static const static_tree_desc  static_bl_desc =
 
 static void init_block       (deflate_state *s);
 static void pqdownheap       (unsigned char *depth, int *heap, const int heap_len, ct_data *tree, int k);
-static void gen_bitlen       (deflate_state *s, tree_desc *desc);
 static void build_tree       (deflate_state *s, tree_desc *desc);
+static void gen_bitlen       (deflate_state *s, tree_desc *desc);
 static void scan_tree        (deflate_state *s, ct_data *tree, int max_code);
 static void send_tree        (deflate_state *s, ct_data *tree, int max_code);
 static int  build_bl_tree    (deflate_state *s);
@@ -123,6 +123,14 @@ static void init_block(deflate_state *s) {
 /* Index within the heap array of least frequent node in the Huffman tree */
 
 
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+    (tree[n].Freq < tree[m].Freq || \
+    (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
 /* ===========================================================================
  * Remove the smallest element from the heap and recreate the heap with
  * one less element. Updates heap and heap_len. Used by build_tree().
@@ -133,14 +141,6 @@ static void init_block(deflate_state *s) {
     pqdownheap(depth, heap, s->heap_len, tree, SMALLEST); \
 }
 
-/* ===========================================================================
- * Compares to subtrees, using the tree depth as tie breaker when
- * the subtrees have equal frequency. This minimizes the worst case length.
- */
-#define smaller(tree, n, m, depth) \
-    (tree[n].Freq < tree[m].Freq || \
-    (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
-
 /* ===========================================================================
  * Restore the heap property by moving down the tree starting at node k,
  * exchanging a node with the smallest of its two sons if necessary, stopping
@@ -172,6 +172,101 @@ static void pqdownheap(unsigned char *depth, int *heap, const int heap_len, ct_d
     heap[k] = v;
 }
 
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ *     and corresponding code. The length opt_len is updated; static_len is
+ *     also updated if stree is not null. The field max_code is set.
+ */
+static void build_tree(deflate_state *s, tree_desc *desc) {
+    /* desc: the tree descriptor */
+    unsigned char *depth  = s->depth;
+    int *heap             = s->heap;
+    ct_data *tree         = desc->dyn_tree;
+    const ct_data *stree  = desc->stat_desc->static_tree;
+    int elems             = desc->stat_desc->elems;
+    int n, m;          /* iterate over heap elements */
+    int max_code = -1; /* largest code with non zero frequency */
+    int node;          /* new node being created */
+
+    /* Construct the initial heap, with least frequent element in
+     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+     * heap[0] is not used.
+     */
+    s->heap_len = 0;
+    s->heap_max = HEAP_SIZE;
+
+    for (n = 0; n < elems; n++) {
+        if (tree[n].Freq != 0) {
+            heap[++(s->heap_len)] = max_code = n;
+            depth[n] = 0;
+        } else {
+            tree[n].Len = 0;
+        }
+    }
+
+    /* The pkzip format requires that at least one distance code exists,
+     * and that at least one bit should be sent even if there is only one
+     * possible code. So to avoid special checks later on we force at least
+     * two codes of non zero frequency.
+     */
+    while (s->heap_len < 2) {
+        node = heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+        tree[node].Freq = 1;
+        depth[node] = 0;
+        s->opt_len--;
+        if (stree)
+            s->static_len -= stree[node].Len;
+        /* node is 0 or 1 so it does not have extra bits */
+    }
+    desc->max_code = max_code;
+
+    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+     * establish sub-heaps of increasing lengths:
+     */
+    for (n = s->heap_len/2; n >= 1; n--)
+        pqdownheap(depth, heap, s->heap_len, tree, n);
+
+    /* Construct the Huffman tree by repeatedly combining the least two
+     * frequent nodes.
+     */
+    node = elems;              /* next internal node of the tree */
+    do {
+        pqremove(s, depth, heap, tree, n);  /* n = node of least frequency */
+        m = heap[SMALLEST]; /* m = node of next least frequency */
+
+        heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+        heap[--(s->heap_max)] = m;
+
+        /* Create a new node father of n and m */
+        tree[node].Freq = tree[n].Freq + tree[m].Freq;
+        depth[node] = (unsigned char)((depth[n] >= depth[m] ?
+                                          depth[n] : depth[m]) + 1);
+        tree[n].Dad = tree[m].Dad = (uint16_t)node;
+#ifdef DUMP_BL_TREE
+        if (tree == s->bl_tree) {
+            fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)",
+                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+        }
+#endif
+        /* and insert the new node in the heap */
+        heap[SMALLEST] = node++;
+        pqdownheap(depth, heap, s->heap_len, tree, SMALLEST);
+    } while (s->heap_len >= 2);
+
+    heap[--(s->heap_max)] = heap[SMALLEST];
+
+    /* At this point, the fields freq and dad are set. We can now
+     * generate the bit lengths.
+     */
+    gen_bitlen(s, (tree_desc *)desc);
+
+    /* The field len is now set, we can generate the bit codes */
+    gen_codes((ct_data *)tree, max_code, s->bl_count);
+}
+
 /* ===========================================================================
  * Compute the optimal bit lengths for a tree and update the total bit length
  * for the current block.
@@ -180,7 +275,7 @@ static void pqdownheap(unsigned char *depth, int *heap, const int heap_len, ct_d
  * OUT assertions: the field len is set to the optimal bit length, the
  *     array bl_count contains the frequencies for each bit length.
  *     The length opt_len is updated; static_len is also updated if stree is
- *     not null.
+ *     not null. Used by build_tree().
  */
 static void gen_bitlen(deflate_state *s, tree_desc *desc) {
     /* desc: the tree descriptor */
@@ -275,7 +370,7 @@ static void gen_bitlen(deflate_state *s, tree_desc *desc) {
  * IN assertion: the array bl_count contains the bit length statistics for
  * the given tree and the field len is set for all tree elements.
  * OUT assertion: the field code is set for all tree elements of non
- *     zero code length.
+ *     zero code length. Used by build_tree().
  */
 Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) {
     /* tree: the tree to decorate */
@@ -311,101 +406,6 @@ Z_INTERNAL void gen_codes(ct_data *tree, int max_code, uint16_t *bl_count) {
     }
 }
 
-/* ===========================================================================
- * Construct one Huffman tree and assigns the code bit strings and lengths.
- * Update the total bit length for the current block.
- * IN assertion: the field freq is set for all tree elements.
- * OUT assertions: the fields len and code are set to the optimal bit length
- *     and corresponding code. The length opt_len is updated; static_len is
- *     also updated if stree is not null. The field max_code is set.
- */
-static void build_tree(deflate_state *s, tree_desc *desc) {
-    /* desc: the tree descriptor */
-    unsigned char *depth  = s->depth;
-    int *heap             = s->heap;
-    ct_data *tree         = desc->dyn_tree;
-    const ct_data *stree  = desc->stat_desc->static_tree;
-    int elems             = desc->stat_desc->elems;
-    int n, m;          /* iterate over heap elements */
-    int max_code = -1; /* largest code with non zero frequency */
-    int node;          /* new node being created */
-
-    /* Construct the initial heap, with least frequent element in
-     * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
-     * heap[0] is not used.
-     */
-    s->heap_len = 0;
-    s->heap_max = HEAP_SIZE;
-
-    for (n = 0; n < elems; n++) {
-        if (tree[n].Freq != 0) {
-            heap[++(s->heap_len)] = max_code = n;
-            depth[n] = 0;
-        } else {
-            tree[n].Len = 0;
-        }
-    }
-
-    /* The pkzip format requires that at least one distance code exists,
-     * and that at least one bit should be sent even if there is only one
-     * possible code. So to avoid special checks later on we force at least
-     * two codes of non zero frequency.
-     */
-    while (s->heap_len < 2) {
-        node = heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
-        tree[node].Freq = 1;
-        depth[node] = 0;
-        s->opt_len--;
-        if (stree)
-            s->static_len -= stree[node].Len;
-        /* node is 0 or 1 so it does not have extra bits */
-    }
-    desc->max_code = max_code;
-
-    /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
-     * establish sub-heaps of increasing lengths:
-     */
-    for (n = s->heap_len/2; n >= 1; n--)
-        pqdownheap(depth, heap, s->heap_len, tree, n);
-
-    /* Construct the Huffman tree by repeatedly combining the least two
-     * frequent nodes.
-     */
-    node = elems;              /* next internal node of the tree */
-    do {
-        pqremove(s, depth, heap, tree, n);  /* n = node of least frequency */
-        m = heap[SMALLEST]; /* m = node of next least frequency */
-
-        heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
-        heap[--(s->heap_max)] = m;
-
-        /* Create a new node father of n and m */
-        tree[node].Freq = tree[n].Freq + tree[m].Freq;
-        depth[node] = (unsigned char)((depth[n] >= depth[m] ?
-                                          depth[n] : depth[m]) + 1);
-        tree[n].Dad = tree[m].Dad = (uint16_t)node;
-#ifdef DUMP_BL_TREE
-        if (tree == s->bl_tree) {
-            fprintf(stderr, "\nnode %d(%d), sons %d(%d) %d(%d)",
-                    node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
-        }
-#endif
-        /* and insert the new node in the heap */
-        heap[SMALLEST] = node++;
-        pqdownheap(depth, heap, s->heap_len, tree, SMALLEST);
-    } while (s->heap_len >= 2);
-
-    heap[--(s->heap_max)] = heap[SMALLEST];
-
-    /* At this point, the fields freq and dad are set. We can now
-     * generate the bit lengths.
-     */
-    gen_bitlen(s, (tree_desc *)desc);
-
-    /* The field len is now set, we can generate the bit codes */
-    gen_codes((ct_data *)tree, max_code, s->bl_count);
-}
-
 /* ===========================================================================
  * Scan a literal or distance tree to determine the frequencies of the codes
  * in the bit length tree.