Line data Source code
1 : /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 : /* 3 : Copyright (C) 2009 Red Hat, Inc. 4 : 5 : This library is free software; you can redistribute it and/or 6 : modify it under the terms of the GNU Lesser General Public 7 : License as published by the Free Software Foundation; either 8 : version 2.1 of the License, or (at your option) any later version. 9 : 10 : This library is distributed in the hope that it will be useful, 11 : but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 : Lesser General Public License for more details. 14 : 15 : You should have received a copy of the GNU Lesser General Public 16 : License along with this library; if not, see <http://www.gnu.org/licenses/>. 17 : */ 18 : #include <config.h> 19 : 20 : #ifdef QUIC_FAMILY_8BPC 21 : #undef QUIC_FAMILY_8BPC 22 : #define FNAME(name) name##_8bpc 23 : #define VNAME(name) name##_8bpc 24 : #define BPC 8 25 : #endif 26 : 27 : 28 : #ifdef QUIC_FAMILY_5BPC 29 : #undef QUIC_FAMILY_5BPC 30 : #define FNAME(name) name##_5bpc 31 : #define VNAME(name) name##_5bpc 32 : #define BPC 5 33 : #endif 34 : 35 2568940 : static inline unsigned int FNAME(golomb_code)(const BYTE n, const unsigned int l) 36 : { 37 2568940 : return VNAME(family).golomb_code[n][l]; 38 : } 39 : 40 4623556 : static inline unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l) 41 : { 42 4623556 : return VNAME(family).golomb_code_len[n][l]; 43 : } 44 : 45 2568940 : static void FNAME(golomb_coding)(Encoder *encoder, const BYTE n, const unsigned int l) 46 : { 47 2568940 : encode(encoder, FNAME(golomb_code)(n, l), FNAME(golomb_code_len)(n, l)); 48 2568940 : } 49 : 50 2568940 : static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits, 51 : unsigned int * const codewordlen) 52 : { 53 2568940 : if (bits > VNAME(family).notGRprefixmask[l]) { /*GR*/ 54 1316477 : const unsigned int zeroprefix = cnt_l_zeroes(bits); /* leading zeroes in codeword */ 55 1316477 : const unsigned int cwlen = zeroprefix + 1 + l; /* codeword length */ 56 1316477 : (*codewordlen) = cwlen; 57 1316477 : return (zeroprefix << l) | ((bits >> (32 - cwlen)) & bppmask[l]); 58 : } else { /* not-GR */ 59 1252463 : const unsigned int cwlen = VNAME(family).notGRcwlen[l]; 60 1252463 : (*codewordlen) = cwlen; 61 1252463 : return VNAME(family).nGRcodewords[l] + ((bits) >> (32 - cwlen) & 62 1252463 : bppmask[VNAME(family).notGRsuffixlen[l]]); 63 : } 64 : } 65 : 66 : /* update the bucket using just encoded curval */ 67 273522 : static void FNAME(update_model)(CommonState *state, s_bucket * const bucket, 68 : const BYTE curval) 69 : { 70 : SPICE_VERIFY(BPC >= 1); 71 273522 : spice_return_if_fail (bucket != NULL); 72 : 73 273522 : const unsigned int bpp = BPC; 74 273522 : COUNTER * const pcounters = bucket->pcounters; 75 : unsigned int i; 76 : unsigned int bestcode; 77 : unsigned int bestcodelen; 78 : 79 : /* update counters, find minimum */ 80 : 81 273522 : bestcode = bpp - 1; 82 273522 : bestcodelen = (pcounters[bestcode] += FNAME(golomb_code_len)(curval, bestcode)); 83 : 84 2054616 : for (i = bpp - 2; i < bpp; i--) { /* NOTE: expression i<bpp for signed int i would be: i>=0 */ 85 1781094 : const unsigned int ithcodelen = (pcounters[i] += FNAME(golomb_code_len)(curval, i)); 86 : 87 1781094 : if (ithcodelen < bestcodelen) { 88 88506 : bestcode = i; 89 88506 : bestcodelen = ithcodelen; 90 : } 91 : } 92 : 93 273522 : bucket->bestcode = bestcode; /* store the found minimum */ 94 : 95 273522 : if (bestcodelen > state->wm_trigger) { /* halving counters? */ 96 118320 : for (i = 0; i < bpp; i++) { 97 104620 : pcounters[i] >>= 1; 98 : } 99 : } 100 : } 101 : 102 5411402 : static s_bucket *FNAME(find_bucket)(Channel *channel, const unsigned int val) 103 : { 104 5411402 : spice_extra_assert(val < (0x1U << BPC)); 105 : 106 : /* The and (&) here is to avoid buffer overflows in case of garbage or malicious 107 : * attempts. Is much faster then using comparisons and save us from such situations. 108 : * Note that on normal build the check above won't be compiled as this code path 109 : * is pretty hot and would cause speed regressions. 110 : */ 111 5411402 : return channel->_buckets_ptrs[val & ((1U << BPC) - 1)]; 112 : } 113 : 114 : #undef FNAME 115 : #undef VNAME 116 : #undef BPC