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
64 zvec_decode (uword coding, uword zdata, uword * n_zdata_bits)
66 uword c, d, result, n_bits;
67 uword explicit_end, implicit_end;
73 c = first_set (coding);
74 implicit_end = c == coding;
75 explicit_end = (zdata & 1) & ~implicit_end;
76 d = (zdata >> explicit_end) & (c - 1);
77 if (explicit_end | implicit_end)
80 n_bits += min_log2 (c) + explicit_end;
90 n_bits = BITS (uword);
92 *n_zdata_bits = n_bits;
97 zvec_encode (uword coding, uword data, uword * n_result_bits)
99 uword c, shift, result;
100 uword explicit_end, implicit_end;
102 /* Data must be in range. Note special coding == 0
103 would break for data - 1 <= coding. */
104 ASSERT (data <= coding - 1);
109 c = first_set (coding);
110 implicit_end = c == coding;
111 explicit_end = ((data & (c - 1)) == data);
112 if (explicit_end | implicit_end)
114 uword t = explicit_end & ~implicit_end;
115 result = ((data << t) | t) << shift;
117 /* data bits */ (c == 0 ? BITS (uword) : min_log2 (c))
118 /* shift bits */ + shift + t;
132 get_data (void *data, uword data_bytes, uword is_signed)
135 return is_signed ? zvec_signed_to_unsigned (*(i8 *) data) : *(u8 *) data;
136 else if (data_bytes == 2)
137 return is_signed ? zvec_signed_to_unsigned (*(i16 *) data) : *(u16 *)
139 else if (data_bytes == 4)
140 return is_signed ? zvec_signed_to_unsigned (*(i32 *) data) : *(u32 *)
142 else if (data_bytes == 8)
143 return is_signed ? zvec_signed_to_unsigned (*(i64 *) data) : *(u64 *)
153 put_data (void *data, uword data_bytes, uword is_signed, uword x)
158 *(i8 *) data = zvec_unsigned_to_signed (x);
162 else if (data_bytes == 2)
165 *(i16 *) data = zvec_unsigned_to_signed (x);
169 else if (data_bytes == 4)
172 *(i32 *) data = zvec_unsigned_to_signed (x);
176 else if (data_bytes == 8)
179 *(i64 *) data = zvec_unsigned_to_signed (x);
189 always_inline uword *
190 zvec_encode_inline (uword * zvec,
195 uword n_data, uword data_bytes, uword is_signed)
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,
257 uword n_data, uword data_bytes, uword is_signed)
262 n_max = coding_max_n_bits (coding);
267 z0 = clib_bitmap_get_multiple (zvec, i, n_max);
268 d0 = zvec_decode (coding, z0, &l0);
270 put_data (data + 0 * data_stride, data_bytes, is_signed, d0);
271 data += 1 * data_stride;
277 #define _(TYPE,IS_SIGNED) \
278 void zvec_decode_##TYPE (uword * zvec, \
279 uword * zvec_n_bits, \
285 return zvec_decode_inline (zvec, zvec_n_bits, \
287 data, data_stride, n_data, \
288 /* data_bytes */ sizeof (TYPE), \
289 /* is_signed */ IS_SIGNED); \
292 _(u8, /* is_signed */ 0);
293 _(u16, /* is_signed */ 0);
294 _(u32, /* is_signed */ 0);
295 _(u64, /* is_signed */ 0);
296 _(i8, /* is_signed */ 1);
297 _(i16, /* is_signed */ 1);
298 _(i32, /* is_signed */ 1);
299 _(i64, /* is_signed */ 1);
303 /* Compute number of bits needed to encode given histogram. */
305 zvec_coding_bits (uword coding, uword * histogram_counts, uword min_bits)
307 uword n_type_bits, n_bits;
308 uword this_count, last_count, max_count_index;
314 max_count_index = vec_len (histogram_counts) - 1;
316 /* Coding is not large enough to encode given data. */
317 if (coding <= max_count_index)
323 b = first_set (coding);
328 histogram_counts[i > max_count_index ? max_count_index : i - 1];
330 /* No more data to encode? */
331 if (this_count == last_count)
334 /* Last coding is i 0 ... 0 so we don't need an extra type bit. */
338 n_bits += (this_count - last_count) * (n_type_bits + l);
340 /* This coding cannot be minimal: so return. */
341 if (n_bits >= min_bits)
344 last_count = this_count;
353 _zvec_coding_from_histogram (void *histogram,
355 uword histogram_elt_count_offset,
356 uword histogram_elt_bytes,
357 uword max_value_to_encode,
358 zvec_coding_info_t * coding_return)
360 uword coding, min_coding;
361 uword min_coding_bits, coding_bits;
362 uword i, n_bits_set, total_count;
364 zvec_histogram_count_t *h_count = histogram + histogram_elt_count_offset;
366 if (histogram_len < 1)
368 coding_return->coding = 0;
369 coding_return->min_coding_bits = 0;
370 coding_return->n_data = 0;
371 coding_return->n_codes = 0;
372 coding_return->ave_coding_bits = 0;
377 counts = vec_new (uword, histogram_len);
378 for (i = 0; i < histogram_len; i++)
380 zvec_histogram_count_t this_count = h_count[0];
381 total_count += this_count;
382 counts[i] = total_count;
384 (zvec_histogram_count_t *) ((void *) h_count + histogram_elt_bytes);
388 min_coding_bits = ~0;
392 max_value_to_encode !=
393 ~0 ? (1 + max_value_to_encode) : vec_len (counts);
394 uword max_coding = max_pow2 (2 * base_coding);
396 for (n_bits_set = 1; n_bits_set <= 8; n_bits_set++)
398 for (coding = pow2_mask (n_bits_set);
400 coding = next_with_same_number_of_set_bits (coding))
402 coding_bits = zvec_coding_bits (coding, counts, min_coding_bits);
403 if (coding_bits >= min_coding_bits)
405 min_coding_bits = coding_bits;
413 coding_return->coding = min_coding;
414 coding_return->min_coding_bits = min_coding_bits;
415 coding_return->n_data = total_count;
416 coding_return->n_codes = vec_len (counts);
417 coding_return->ave_coding_bits =
418 (f64) min_coding_bits / (f64) total_count;
427 format_zvec_coding (u8 * s, va_list * args)
429 zvec_coding_info_t *c = va_arg (*args, zvec_coding_info_t *);
431 "zvec coding 0x%x, %d elts, %d codes, %d bits total, %.4f ave bits/code",
432 c->coding, c->n_data, c->n_codes, c->min_coding_bits,
437 * fd.io coding-style-patch-verification: ON
440 * eval: (c-set-style "gnu")