3 /***********************************************************************
8 * Pack some multiple of four words holding two-bit tags (in the low
9 * two bits of each byte) into an integral number of words, i.e.,
11 * NOTE: Pad the input out with zeroes to a multiple of four words!
14 WK_pack_2bits(WK_word
* source_buf
,
18 register WK_word
* src_next
= source_buf
;
19 WK_word
* dest_next
= dest_buf
;
21 while (src_next
< source_end
) {
22 register WK_word temp
= src_next
[0];
23 temp
|= (src_next
[1] << 2);
24 temp
|= (src_next
[2] << 4);
25 temp
|= (src_next
[3] << 6);
37 * Pack an even number of words holding 4-bit patterns in the low bits
38 * of each byte into half as many words.
39 * note: pad out the input with zeroes to an even number of words!
43 WK_pack_4bits(WK_word
* source_buf
,
46 register WK_word
* src_next
= source_buf
;
47 WK_word
* dest_next
= dest_buf
;
49 /* this loop should probably be unrolled */
50 while (src_next
< source_end
) {
51 register WK_word temp
= src_next
[0];
52 temp
|= (src_next
[1] << 4);
64 * Pack a sequence of three ten bit items into one word.
65 * note: pad out the input with zeroes to an even number of words!
68 WK_pack_3_tenbits(WK_word
* source_buf
,
72 register WK_word
* src_next
= source_buf
;
73 WK_word
* dest_next
= dest_buf
;
75 /* this loop should probably be unrolled */
76 while (src_next
< source_end
) {
77 register WK_word temp
= src_next
[0];
78 temp
|= (src_next
[1] << 10);
79 temp
|= (src_next
[2] << 20);
90 /***************************************************************************
91 * WKdm_compress()---THE COMPRESSOR
95 WKdm_compress (WK_word
* src_buf
,
97 unsigned int num_input_words
)
99 DictionaryElement dictionary
[DICTIONARY_SIZE
];
101 /* arrays that hold output data in intermediate form during modeling */
102 /* and whose contents are packed into the actual output after modeling */
104 /* sizes of these arrays should be increased if you want to compress
105 * pages larger than 4KB
107 WK_word tempTagsArray
[300]; /* tags for everything */
108 WK_word tempQPosArray
[300]; /* queue positions for matches */
109 WK_word tempLowBitsArray
[1200]; /* low bits for partial matches */
111 /* boundary_tmp will be used for keeping track of what's where in
112 * the compressed page during packing
114 WK_word
* boundary_tmp
;
116 /* Fill pointers for filling intermediate arrays (of queue positions
117 * and low bits) during encoding.
118 * Full words go straight to the destination buffer area reserved
119 * for them. (Right after where the tags go.)
121 WK_word
* next_full_patt
;
122 char* next_tag
= (char *) tempTagsArray
;
123 char* next_qp
= (char *) tempQPosArray
;
124 WK_word
* next_low_bits
= tempLowBitsArray
;
126 WK_word
* next_input_word
= src_buf
;
127 WK_word
* end_of_input
= src_buf
+ num_input_words
;
131 next_full_patt
= dest_buf
+ TAGS_AREA_OFFSET
+ (num_input_words
/ 16);
134 printf("\nIn WKdm_compress\n");
135 printf("About to actually compress, src_buf is %u\n", src_buf
);
136 printf("dictionary is at %u\n", dictionary
);
137 printf("dest_buf is %u next_full_patt is %u\n", dest_buf
, next_full_patt
);
141 while (next_input_word
< end_of_input
)
143 WK_word
*dict_location
;
145 WK_word input_word
= *next_input_word
;
147 /* compute hash value, which is a byte offset into the dictionary,
148 * and add it to the base address of the dictionary. Cast back and
149 * forth to/from char * so no shifts are needed
153 (((char*) dictionary
) + HASH_TO_DICT_BYTE_OFFSET(input_word
));
155 dict_word
= *dict_location
;
157 if (input_word
== dict_word
)
159 RECORD_EXACT(dict_location
- dictionary
);
161 else if (input_word
== 0) {
166 WK_word input_high_bits
= HIGH_BITS(input_word
);
167 if (input_high_bits
== HIGH_BITS(dict_word
)) {
168 RECORD_PARTIAL(dict_location
- dictionary
, LOW_BITS(input_word
));
169 *dict_location
= input_word
;
172 RECORD_MISS(input_word
);
173 *dict_location
= input_word
;
180 printf("AFTER MODELING in WKdm_compress()\n"); fflush(stdout
);
181 printf("tempTagsArray holds %u bytes\n",
182 next_tag
- (char *) tempTagsArray
);
183 printf("tempQPosArray holds %u bytes\n",
184 next_qp
- (char *) tempQPosArray
);
185 printf("tempLowBitsArray holds %u bytes\n",
186 (char *) next_low_bits
- (char *) tempLowBitsArray
);
188 printf("next_full_patt is %u\n",
189 (unsigned long) next_full_patt
);
191 printf(" i.e., there are %u full patterns\n",
192 next_full_patt
- (dest_buf
+ TAGS_AREA_OFFSET
+ (num_input_words
/ 16)));
196 WK_word
*arr
=(dest_buf
+ TAGS_AREA_OFFSET
+ (num_input_words
/ 16));
198 printf(" first 20 full patterns are: \n");
199 for (i
= 0; i
< 20; i
++) {
200 printf(" %d", arr
[i
]);
206 /* Record (into the header) where we stopped writing full words,
207 * which is where we will pack the queue positions. (Recall
208 * that we wrote the full words directly into the dest buffer
212 SET_QPOS_AREA_START(dest_buf
,next_full_patt
);
214 /* Pack the tags into the tags area, between the page header
215 * and the full words area. We don't pad for the packer
216 * because we assume that the page size is a multiple of 16.
220 printf("about to pack %u bytes holding tags\n",
221 next_tag
- (char *) tempTagsArray
);
224 char* arr
= (char *) tempTagsArray
;
226 printf(" first 200 tags are: \n");
227 for (i
= 0; i
< 200; i
++) {
228 printf(" %d", arr
[i
]);
234 boundary_tmp
= WK_pack_2bits(tempTagsArray
,
235 (WK_word
*) next_tag
,
236 dest_buf
+ HEADER_SIZE_IN_WORDS
);
239 printf("packing tags stopped at %u\n", boundary_tmp
);
242 /* Pack the queue positions into the area just after
243 * the full words. We have to round up the source
244 * region to a multiple of two words.
248 unsigned int num_bytes_to_pack
= next_qp
- (char *) tempQPosArray
;
249 unsigned int num_packed_words
= (num_bytes_to_pack
+ 7) >> 3; // ceil((double) num_bytes_to_pack / 8);
250 unsigned int num_source_words
= num_packed_words
* 2;
251 WK_word
* endQPosArray
= tempQPosArray
+ num_source_words
;
253 /* Pad out the array with zeros to avoid corrupting real packed
255 for (; /* next_qp is already set as desired */
256 next_qp
< (char*)endQPosArray
;
262 printf("about to pack %u (bytes holding) queue posns.\n",
264 printf("packing them from %u words into %u words\n",
265 num_source_words
, num_packed_words
);
266 printf("dest is range %u to %u\n",
267 next_full_patt
, next_full_patt
+ num_packed_words
);
269 char *arr
= (char *) tempQPosArray
;
270 printf(" first 200 queue positions are: \n");
271 for (i
= 0; i
< 200; i
++) {
272 printf(" %d", arr
[i
]);
278 boundary_tmp
= WK_pack_4bits(tempQPosArray
,
282 printf("Packing of queue positions stopped at %u\n", boundary_tmp
);
285 /* Record (into the header) where we stopped packing queue positions,
286 * which is where we will start packing low bits.
288 SET_LOW_BITS_AREA_START(dest_buf
,boundary_tmp
);
292 /* Pack the low bit patterns into the area just after
293 * the queue positions. We have to round up the source
294 * region to a multiple of three words.
298 unsigned int num_tenbits_to_pack
=
299 next_low_bits
- tempLowBitsArray
;
300 unsigned int num_packed_words
= (num_tenbits_to_pack
+ 2) / 3; //ceil((double) num_tenbits_to_pack / 3);
301 unsigned int num_source_words
= num_packed_words
* 3;
302 WK_word
* endLowBitsArray
= tempLowBitsArray
+ num_source_words
;
304 /* Pad out the array with zeros to avoid corrupting real packed
307 for (; /* next_low_bits is already set as desired */
308 next_low_bits
< endLowBitsArray
;
314 printf("about to pack low bits\n");
315 printf("num_tenbits_to_pack is %u\n", num_tenbits_to_pack
);
316 printf("endLowBitsArray is %u\n", endLowBitsArray
);
319 boundary_tmp
= WK_pack_3_tenbits (tempLowBitsArray
,
323 SET_LOW_BITS_AREA_END(dest_buf
,boundary_tmp
);
327 return ((char *) boundary_tmp
- (char *) dest_buf
);