Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

304 lines
6.8 KiB

  1. /*
  2. * enctree.c
  3. *
  4. * Encode trees into output data
  5. */
  6. #define EXT extern
  7. #include "encoder.h"
  8. /*
  9. * Encode a tree
  10. */
  11. static void WriteRepTree(
  12. t_encoder_context *context,
  13. byte *pLen,
  14. byte *pLastLen,
  15. int Num
  16. )
  17. {
  18. int i;
  19. int j;
  20. int Same;
  21. ushort SmallFreq[2*24];
  22. ushort MiniCode[24];
  23. char MiniLen[24];
  24. char k;
  25. byte temp_store;
  26. byte * z=context->enc_output_buffer_curpos;
  27. static const byte Modulo17Lookup[] =
  28. {
  29. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
  30. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
  31. };
  32. memset(SmallFreq, 0, sizeof(SmallFreq));
  33. temp_store = pLen[Num];
  34. pLen[Num] = 123;
  35. for (i = 0; i < Num; i++)
  36. {
  37. Same = 0;
  38. /* Count the number of consecutive elements which have the same length */
  39. /* No need to check against array boundary, because the last element has */
  40. /* a nonsense value */
  41. for (j = i+1; pLen[j] == pLen[i]; j++)
  42. Same++;
  43. /* If more than 3, compress this information */
  44. if (Same >= TREE_ENC_REP_MIN)
  45. {
  46. /* Special case if they're zeroes */
  47. if (!pLen[i])
  48. {
  49. if (Same > TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST + TREE_ENC_REP_ZERO_SECOND - 1)
  50. Same = TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST + TREE_ENC_REP_ZERO_SECOND - 1;
  51. if (Same <= TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST - 1)
  52. SmallFreq[17]++;
  53. else
  54. SmallFreq[18]++;
  55. }
  56. else
  57. {
  58. if (Same > TREE_ENC_REP_MIN + TREE_ENC_REP_SAME_FIRST - 1)
  59. Same = TREE_ENC_REP_MIN + TREE_ENC_REP_SAME_FIRST - 1;
  60. SmallFreq[ Modulo17Lookup[ pLastLen[i]-pLen[i]+17 ] ]++;
  61. SmallFreq[19]++;
  62. }
  63. i += Same-1;
  64. }
  65. else
  66. SmallFreq[ Modulo17Lookup[ pLastLen[i]-pLen[i]+17 ] ]++;
  67. }
  68. make_tree(
  69. context,
  70. 20,
  71. SmallFreq,
  72. (byte *) MiniLen,
  73. MiniCode,
  74. true
  75. );
  76. /* max 10 byte output overrun */
  77. for (i = 0; i < 20; i++)
  78. {
  79. output_bits(context, 4, MiniLen[i]);
  80. }
  81. /* Output original tree with new code */
  82. for (i = 0; i < Num; i++)
  83. {
  84. Same = 0;
  85. /* Count the number of consecutive elements which have the same length */
  86. /* No need to check against array boundary, because the last element has */
  87. /* a nonsense value */
  88. for (j = i+1; pLen[j] == pLen[i]; j++)
  89. Same++;
  90. /* If more than 3, we can do something */
  91. if (Same >= TREE_ENC_REP_MIN)
  92. {
  93. if (!pLen[i]) /* Zeroes */
  94. {
  95. if (Same > TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST + TREE_ENC_REP_ZERO_SECOND - 1)
  96. Same = TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST + TREE_ENC_REP_ZERO_SECOND - 1;
  97. if (Same <= TREE_ENC_REP_MIN + TREE_ENC_REP_ZERO_FIRST - 1)
  98. k = 17;
  99. else
  100. k = 18;
  101. }
  102. else
  103. {
  104. if (Same > TREE_ENC_REP_MIN + TREE_ENC_REP_SAME_FIRST - 1)
  105. Same = TREE_ENC_REP_MIN + TREE_ENC_REP_SAME_FIRST - 1;
  106. k = 19;
  107. }
  108. }
  109. else
  110. k = Modulo17Lookup[ pLastLen[i]-pLen[i]+17 ];
  111. output_bits(context, MiniLen[k], MiniCode[k]);
  112. if (k == 17)
  113. {
  114. output_bits(context, TREE_ENC_REPZ_FIRST_EXTRA_BITS, Same-TREE_ENC_REP_MIN);
  115. i += Same-1;
  116. }
  117. else if (k == 18)
  118. {
  119. output_bits(context, TREE_ENC_REPZ_SECOND_EXTRA_BITS, Same-(TREE_ENC_REP_MIN+TREE_ENC_REP_ZERO_FIRST));
  120. i += Same-1;
  121. }
  122. else if (k == 19)
  123. {
  124. output_bits(context, TREE_ENC_REP_SAME_EXTRA_BITS, Same-TREE_ENC_REP_MIN);
  125. k = Modulo17Lookup[ pLastLen[i]-pLen[i]+17 ];
  126. output_bits(context, MiniLen[k], MiniCode[k]);
  127. i += Same-1;
  128. }
  129. }
  130. pLen[Num] = temp_store;
  131. memcpy(pLastLen, pLen, Num);
  132. }
  133. void create_trees(t_encoder_context *context, bool generate_codes)
  134. {
  135. /*
  136. * Assumption: We can trash PtrLen[NUM_CHARS+(NUM_POSITION_SLOTS*NUM_LENGTHS))], since
  137. * we allocated space for it earlier
  138. */
  139. make_tree(
  140. context,
  141. NUM_CHARS+(context->enc_num_position_slots*(NUM_PRIMARY_LENGTHS+1)),
  142. context->enc_main_tree_freq,
  143. context->enc_main_tree_len,
  144. context->enc_main_tree_code,
  145. generate_codes
  146. );
  147. make_tree(
  148. context,
  149. NUM_SECONDARY_LENGTHS,
  150. context->enc_secondary_tree_freq,
  151. context->enc_secondary_tree_len,
  152. context->enc_secondary_tree_code,
  153. generate_codes
  154. );
  155. make_tree(
  156. context,
  157. ALIGNED_NUM_ELEMENTS,
  158. context->enc_aligned_tree_freq,
  159. context->enc_aligned_tree_len,
  160. context->enc_aligned_tree_code,
  161. true
  162. );
  163. }
  164. void fix_tree_cost_estimates(t_encoder_context *context)
  165. {
  166. /*
  167. * We're only creating trees for estimation purposes and we do not
  168. * want to encode the tree. However, the following loops will set
  169. * the frequency zero tree element lengths to values other than
  170. * zero, so that the optimal encoder won't get confused when it
  171. * tries to estimate the number of bits it would take to output an
  172. * element.
  173. *
  174. * We also set the bit lengths of match length 2's further away
  175. * than MAX_LENGTH_TWO_OFFSET to a large number, so that the
  176. * optimal parser will never select such matches.
  177. */
  178. ulong i;
  179. /* Set zero lengths to some value */
  180. for (i = 0; i< NUM_CHARS; i++)
  181. {
  182. if (context->enc_main_tree_len[i] == 0)
  183. context->enc_main_tree_len[i] = 11;
  184. }
  185. for (; i < NUM_CHARS+(context->enc_num_position_slots*(NUM_PRIMARY_LENGTHS+1)); i++)
  186. {
  187. if (context->enc_main_tree_len[i] == 0)
  188. context->enc_main_tree_len[i] = 12;
  189. }
  190. for (i = 0; i < NUM_SECONDARY_LENGTHS; i++)
  191. {
  192. if (context->enc_secondary_tree_len[i] == 0)
  193. context->enc_secondary_tree_len[i] = 8;
  194. }
  195. prevent_far_matches(context);
  196. }
  197. void prevent_far_matches(t_encoder_context *context)
  198. {
  199. ulong i;
  200. /*
  201. * Set far match length 2's to a high value so they will never
  202. * be chosen.
  203. *
  204. * See description of MAX_GROWTH in encdefs.h
  205. */
  206. for ( i = MP_SLOT(MAX_LENGTH_TWO_OFFSET);
  207. i < context->enc_num_position_slots;
  208. i++
  209. )
  210. {
  211. context->enc_main_tree_len[NUM_CHARS + (i << NL_SHIFT)] = 100;
  212. }
  213. }
  214. /*
  215. * Encode the trees
  216. *
  217. * Assumes trees have already been created with create_trees().
  218. *
  219. * Warning, do not call update_tree_cost_estimates() before encoding
  220. * the trees, since that routine trashes some of the tree elements.
  221. */
  222. void encode_trees(t_encoder_context *context)
  223. {
  224. WriteRepTree(
  225. context,
  226. context->enc_main_tree_len,
  227. context->enc_main_tree_prev_len,
  228. NUM_CHARS
  229. );
  230. WriteRepTree(
  231. context,
  232. &context->enc_main_tree_len[NUM_CHARS],
  233. &context->enc_main_tree_prev_len[NUM_CHARS],
  234. context->enc_num_position_slots * (NUM_PRIMARY_LENGTHS+1)
  235. );
  236. WriteRepTree(
  237. context,
  238. context->enc_secondary_tree_len,
  239. context->enc_secondary_tree_prev_len,
  240. NUM_SECONDARY_LENGTHS
  241. );
  242. }
  243. void encode_aligned_tree(t_encoder_context *context)
  244. {
  245. int i;
  246. make_tree(
  247. context,
  248. ALIGNED_NUM_ELEMENTS,
  249. context->enc_aligned_tree_freq,
  250. context->enc_aligned_tree_len,
  251. context->enc_aligned_tree_code,
  252. true
  253. );
  254. /* Output original tree with new code */
  255. for (i = 0; i < 8; i++)
  256. {
  257. output_bits(context, 3, context->enc_aligned_tree_len[i]);
  258. }
  259. }