@@ -2962,34 +2962,37 @@ impl Heap {
29622962 /// Index within the heap array of least frequent node in the Huffman tree
29632963 const SMALLEST : usize = 1 ;
29642964
2965- fn smaller ( tree : & [ Value ] , n : u32 , m : u32 , depth : & [ u8 ] ) -> bool {
2966- let ( n, m) = ( n as usize , m as usize ) ;
2967-
2968- match Ord :: cmp ( & tree[ n] . freq ( ) , & tree[ m] . freq ( ) ) {
2969- core:: cmp:: Ordering :: Less => true ,
2970- core:: cmp:: Ordering :: Equal => depth[ n] <= depth[ m] ,
2971- core:: cmp:: Ordering :: Greater => false ,
2972- }
2973- }
2974-
29752965 fn pqdownheap ( & mut self , tree : & [ Value ] , mut k : usize ) {
29762966 /* tree: the tree to restore */
29772967 /* k: node to move down */
29782968
2969+ // Given the index $i of a node in the tree, pack the node's frequency and depth
2970+ // into a single integer. The heap ordering logic uses a primary sort on frequency
2971+ // and a secondary sort on depth, so packing both into one integer makes it
2972+ // possible to sort with fewer comparison operations.
2973+ macro_rules! freq_and_depth {
2974+ ( $i: expr) => {
2975+ ( tree[ $i as usize ] . freq( ) as u32 ) << 8 | self . depth[ $i as usize ] as u32
2976+ } ;
2977+ }
2978+
29792979 let v = self . heap [ k] ;
2980+ let v_val = freq_and_depth ! ( v) ;
29802981 let mut j = k << 1 ; /* left son of k */
29812982
29822983 while j <= self . heap_len {
29832984 /* Set j to the smallest of the two sons: */
2985+ let mut j_val = freq_and_depth ! ( self . heap[ j] ) ;
29842986 if j < self . heap_len {
2985- let cond = Self :: smaller ( tree , self . heap [ j + 1 ] , self . heap [ j ] , & self . depth ) ;
2986- if cond {
2987+ let j1_val = freq_and_depth ! ( self . heap[ j + 1 ] ) ;
2988+ if j1_val <= j_val {
29872989 j += 1 ;
2990+ j_val = j1_val;
29882991 }
29892992 }
29902993
29912994 /* Exit if v is smaller than both sons */
2992- if Self :: smaller ( tree , v , self . heap [ j ] , & self . depth ) {
2995+ if v_val <= j_val {
29932996 break ;
29942997 }
29952998
0 commit comments