2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus
18 Permission is hereby granted, free of charge, to any person obtaining
19 a copy of this software and associated documentation files (the
20 "Software"), to deal in the Software without restriction, including
21 without limitation the rights to use, copy, modify, merge, publish,
22 distribute, sublicense, and/or sell copies of the Software, and to
23 permit persons to whom the Software is furnished to do so, subject to
24 the following conditions:
26 The above copyright notice and this permission notice shall be
27 included in all copies or substantial portions of the Software.
29 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 #include <vppinfra/bitmap.h>
39 #include <vppinfra/bitops.h> /* for next_with_same_number_of_set_bits */
40 #include <vppinfra/error.h> /* for ASSERT */
41 #include <vppinfra/mem.h>
42 #include <vppinfra/os.h> /* for os_panic */
43 #include <vppinfra/vec.h>
44 #include <vppinfra/zvec.h>
46 /* Consider coding as bitmap, coding = 2^c_0 + 2^c_1 + ... + 2^c_n
47 With c_0 < c_1 < ... < c_n. coding == 0 represents c_n = BITS (uword).
49 Unsigned integers i = 0 ... are represented as follows:
51 0 <= i < 2^c_0 (i << 1) | (1 << 0) binary: i 1
52 2^c_0 <= i < 2^c_0 + 2^c_1 (i << 2) | (1 << 1) binary: i 1 0
55 Smaller numbers use less bits. Coding is chosen so that encoding
56 of given histogram of typical values gives smallest number of bits.
57 The number and position of coding bits c_i are used to best fit the
58 histogram of typical values.
61 /* Decode given compressed data. Return number of compressed data
63 uword zvec_decode (uword coding, uword zdata, uword * n_zdata_bits)
65 uword c, d, result, n_bits;
66 uword explicit_end, implicit_end;
72 c = first_set (coding);
73 implicit_end = c == coding;
74 explicit_end = (zdata & 1) &~ implicit_end;
75 d = (zdata >> explicit_end) & (c - 1);
76 if (explicit_end | implicit_end)
79 n_bits += min_log2 (c) + explicit_end;
89 n_bits = BITS (uword);
91 *n_zdata_bits = n_bits;
96 zvec_encode (uword coding,
98 uword * n_result_bits)
100 uword c, shift, result;
101 uword explicit_end, implicit_end;
103 /* Data must be in range. Note special coding == 0
104 would break for data - 1 <= coding. */
105 ASSERT (data <= coding - 1);
110 c = first_set (coding);
111 implicit_end = c == coding;
112 explicit_end = ((data & (c - 1)) == data);
113 if (explicit_end | implicit_end)
115 uword t = explicit_end &~ implicit_end;
116 result = ((data << t) | t) << shift;
118 /* data bits */ (c == 0 ? BITS (uword) : min_log2 (c))
119 /* shift bits */ + shift + t;
133 get_data (void * data, uword data_bytes, uword is_signed)
136 return is_signed ? zvec_signed_to_unsigned (*(i8 *) data) : *(u8 *) data;
137 else if (data_bytes == 2)
138 return is_signed ? zvec_signed_to_unsigned (*(i16 *) data) : *(u16 *) data;
139 else if (data_bytes == 4)
140 return is_signed ? zvec_signed_to_unsigned (*(i32 *) data) : *(u32 *) data;
141 else if (data_bytes == 8)
142 return is_signed ? zvec_signed_to_unsigned (*(i64 *) data) : *(u64 *) data;
151 put_data (void * data, uword data_bytes, uword is_signed, uword x)
156 *(i8 *) data = zvec_unsigned_to_signed (x);
160 else if (data_bytes == 2)
163 *(i16 *) data = zvec_unsigned_to_signed (x);
167 else if (data_bytes == 4)
170 *(i32 *) data = zvec_unsigned_to_signed (x);
174 else if (data_bytes == 8)
177 *(i64 *) data = zvec_unsigned_to_signed (x);
187 always_inline uword *
188 zvec_encode_inline (uword * zvec,
204 d0 = get_data (data + 0*data_stride, data_bytes, is_signed);
205 data += 1*data_stride;
208 z0 = zvec_encode (coding, d0, &l0);
209 zvec = clib_bitmap_set_multiple (zvec, i, z0, l0);
217 #define _(TYPE,IS_SIGNED) \
218 uword * zvec_encode_##TYPE (uword * zvec, \
219 uword * zvec_n_bits, \
225 return zvec_encode_inline (zvec, zvec_n_bits, \
227 data, data_stride, n_data, \
228 /* data_bytes */ sizeof (TYPE), \
229 /* is_signed */ IS_SIGNED); \
232 _ (u8, /* is_signed */ 0);
233 _ (u16, /* is_signed */ 0);
234 _ (u32, /* is_signed */ 0);
235 _ (u64, /* is_signed */ 0);
236 _ (i8, /* is_signed */ 1);
237 _ (i16, /* is_signed */ 1);
238 _ (i32, /* is_signed */ 1);
239 _ (i64, /* is_signed */ 1);
244 coding_max_n_bits (uword coding)
247 (void) zvec_decode (coding, 0, &n_bits);
252 zvec_decode_inline (uword * zvec,
264 n_max = coding_max_n_bits (coding);
269 z0 = clib_bitmap_get_multiple (zvec, i, n_max);
270 d0 = zvec_decode (coding, z0, &l0);
272 put_data (data + 0*data_stride, data_bytes, is_signed, d0);
273 data += 1*data_stride;
279 #define _(TYPE,IS_SIGNED) \
280 void zvec_decode_##TYPE (uword * zvec, \
281 uword * zvec_n_bits, \
287 return zvec_decode_inline (zvec, zvec_n_bits, \
289 data, data_stride, n_data, \
290 /* data_bytes */ sizeof (TYPE), \
291 /* is_signed */ IS_SIGNED); \
294 _ (u8, /* is_signed */ 0);
295 _ (u16, /* is_signed */ 0);
296 _ (u32, /* is_signed */ 0);
297 _ (u64, /* is_signed */ 0);
298 _ (i8, /* is_signed */ 1);
299 _ (i16, /* is_signed */ 1);
300 _ (i32, /* is_signed */ 1);
301 _ (i64, /* is_signed */ 1);
305 /* Compute number of bits needed to encode given histogram. */
306 static uword zvec_coding_bits (uword coding,
307 uword * histogram_counts,
310 uword n_type_bits, n_bits;
311 uword this_count, last_count, max_count_index;
317 max_count_index = vec_len (histogram_counts) - 1;
319 /* Coding is not large enough to encode given data. */
320 if (coding <= max_count_index)
326 b = first_set (coding);
330 this_count = histogram_counts[i > max_count_index ? max_count_index : i-1];
332 /* No more data to encode? */
333 if (this_count == last_count)
336 /* Last coding is i 0 ... 0 so we don't need an extra type bit. */
340 n_bits += (this_count - last_count) * (n_type_bits + l);
342 /* This coding cannot be minimal: so return. */
343 if (n_bits >= min_bits)
346 last_count = this_count;
355 _zvec_coding_from_histogram (void * histogram,
357 uword histogram_elt_count_offset,
358 uword histogram_elt_bytes,
359 uword max_value_to_encode,
360 zvec_coding_info_t * coding_return)
362 uword coding, min_coding;
363 uword min_coding_bits, coding_bits;
364 uword i, n_bits_set, total_count;
366 zvec_histogram_count_t * h_count = histogram + histogram_elt_count_offset;
368 if (histogram_len < 1)
370 coding_return->coding = 0;
371 coding_return->min_coding_bits = 0;
372 coding_return->n_data = 0;
373 coding_return->n_codes = 0;
374 coding_return->ave_coding_bits = 0;
379 counts = vec_new (uword, histogram_len);
380 for (i = 0; i < histogram_len; i++)
382 zvec_histogram_count_t this_count = h_count[0];
383 total_count += this_count;
384 counts[i] = total_count;
385 h_count = (zvec_histogram_count_t *) ((void *) h_count + histogram_elt_bytes);
389 min_coding_bits = ~0;
392 uword base_coding = max_value_to_encode != ~0 ? (1 + max_value_to_encode) : vec_len (counts);
393 uword max_coding = max_pow2 (2 * base_coding);
395 for (n_bits_set = 1; n_bits_set <= 8; n_bits_set++)
397 for (coding = pow2_mask (n_bits_set);
399 coding = next_with_same_number_of_set_bits (coding))
401 coding_bits = zvec_coding_bits (coding, counts, min_coding_bits);
402 if (coding_bits >= min_coding_bits)
404 min_coding_bits = coding_bits;
412 coding_return->coding = min_coding;
413 coding_return->min_coding_bits = min_coding_bits;
414 coding_return->n_data = total_count;
415 coding_return->n_codes = vec_len (counts);
416 coding_return->ave_coding_bits = (f64) min_coding_bits / (f64) total_count;
424 u8 * format_zvec_coding (u8 * s, va_list * args)
426 zvec_coding_info_t * c = va_arg (*args, zvec_coding_info_t *);
427 return format (s, "zvec coding 0x%x, %d elts, %d codes, %d bits total, %.4f ave bits/code",
428 c->coding, c->n_data, c->n_codes, c->min_coding_bits, c->ave_coding_bits);