Path: blob/master/Utilities/cmliblzma/liblzma/rangecoder/range_encoder.h
3156 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file range_encoder.h5/// \brief Range Encoder6///7// Authors: Igor Pavlov8// Lasse Collin9//10///////////////////////////////////////////////////////////////////////////////1112#ifndef LZMA_RANGE_ENCODER_H13#define LZMA_RANGE_ENCODER_H1415#include "range_common.h"16#include "price.h"171819/// Maximum number of symbols that can be put pending into lzma_range_encoder20/// structure between calls to lzma_rc_encode(). For LZMA, 48+5 is enough21/// (match with big distance and length followed by range encoder flush).22#define RC_SYMBOLS_MAX 53232425typedef struct {26uint64_t low;27uint64_t cache_size;28uint32_t range;29uint8_t cache;3031/// Number of bytes written out by rc_encode() -> rc_shift_low()32uint64_t out_total;3334/// Number of symbols in the tables35size_t count;3637/// rc_encode()'s position in the tables38size_t pos;3940/// Symbols to encode41enum {42RC_BIT_0,43RC_BIT_1,44RC_DIRECT_0,45RC_DIRECT_1,46RC_FLUSH,47} symbols[RC_SYMBOLS_MAX];4849/// Probabilities associated with RC_BIT_0 or RC_BIT_150probability *probs[RC_SYMBOLS_MAX];5152} lzma_range_encoder;535455static inline void56rc_reset(lzma_range_encoder *rc)57{58rc->low = 0;59rc->cache_size = 1;60rc->range = UINT32_MAX;61rc->cache = 0;62rc->out_total = 0;63rc->count = 0;64rc->pos = 0;65}666768static inline void69rc_forget(lzma_range_encoder *rc)70{71// This must not be called when rc_encode() is partially done.72assert(rc->pos == 0);73rc->count = 0;74}757677static inline void78rc_bit(lzma_range_encoder *rc, probability *prob, uint32_t bit)79{80rc->symbols[rc->count] = bit;81rc->probs[rc->count] = prob;82++rc->count;83}848586static inline void87rc_bittree(lzma_range_encoder *rc, probability *probs,88uint32_t bit_count, uint32_t symbol)89{90uint32_t model_index = 1;9192do {93const uint32_t bit = (symbol >> --bit_count) & 1;94rc_bit(rc, &probs[model_index], bit);95model_index = (model_index << 1) + bit;96} while (bit_count != 0);97}9899100static inline void101rc_bittree_reverse(lzma_range_encoder *rc, probability *probs,102uint32_t bit_count, uint32_t symbol)103{104uint32_t model_index = 1;105106do {107const uint32_t bit = symbol & 1;108symbol >>= 1;109rc_bit(rc, &probs[model_index], bit);110model_index = (model_index << 1) + bit;111} while (--bit_count != 0);112}113114115static inline void116rc_direct(lzma_range_encoder *rc,117uint32_t value, uint32_t bit_count)118{119do {120rc->symbols[rc->count++]121= RC_DIRECT_0 + ((value >> --bit_count) & 1);122} while (bit_count != 0);123}124125126static inline void127rc_flush(lzma_range_encoder *rc)128{129for (size_t i = 0; i < 5; ++i)130rc->symbols[rc->count++] = RC_FLUSH;131}132133134static inline bool135rc_shift_low(lzma_range_encoder *rc,136uint8_t *out, size_t *out_pos, size_t out_size)137{138if ((uint32_t)(rc->low) < (uint32_t)(0xFF000000)139|| (uint32_t)(rc->low >> 32) != 0) {140do {141if (*out_pos == out_size)142return true;143144out[*out_pos] = rc->cache + (uint8_t)(rc->low >> 32);145++*out_pos;146++rc->out_total;147rc->cache = 0xFF;148149} while (--rc->cache_size != 0);150151rc->cache = (rc->low >> 24) & 0xFF;152}153154++rc->cache_size;155rc->low = (rc->low & 0x00FFFFFF) << RC_SHIFT_BITS;156157return false;158}159160161// NOTE: The last two arguments are uint64_t instead of size_t because in162// the dummy version these refer to the size of the whole range-encoded163// output stream, not just to the currently available output buffer space.164static inline bool165rc_shift_low_dummy(uint64_t *low, uint64_t *cache_size, uint8_t *cache,166uint64_t *out_pos, uint64_t out_size)167{168if ((uint32_t)(*low) < (uint32_t)(0xFF000000)169|| (uint32_t)(*low >> 32) != 0) {170do {171if (*out_pos == out_size)172return true;173174++*out_pos;175*cache = 0xFF;176177} while (--*cache_size != 0);178179*cache = (*low >> 24) & 0xFF;180}181182++*cache_size;183*low = (*low & 0x00FFFFFF) << RC_SHIFT_BITS;184185return false;186}187188189static inline bool190rc_encode(lzma_range_encoder *rc,191uint8_t *out, size_t *out_pos, size_t out_size)192{193assert(rc->count <= RC_SYMBOLS_MAX);194195while (rc->pos < rc->count) {196// Normalize197if (rc->range < RC_TOP_VALUE) {198if (rc_shift_low(rc, out, out_pos, out_size))199return true;200201rc->range <<= RC_SHIFT_BITS;202}203204// Encode a bit205switch (rc->symbols[rc->pos]) {206case RC_BIT_0: {207probability prob = *rc->probs[rc->pos];208rc->range = (rc->range >> RC_BIT_MODEL_TOTAL_BITS)209* prob;210prob += (RC_BIT_MODEL_TOTAL - prob) >> RC_MOVE_BITS;211*rc->probs[rc->pos] = prob;212break;213}214215case RC_BIT_1: {216probability prob = *rc->probs[rc->pos];217const uint32_t bound = prob * (rc->range218>> RC_BIT_MODEL_TOTAL_BITS);219rc->low += bound;220rc->range -= bound;221prob -= prob >> RC_MOVE_BITS;222*rc->probs[rc->pos] = prob;223break;224}225226case RC_DIRECT_0:227rc->range >>= 1;228break;229230case RC_DIRECT_1:231rc->range >>= 1;232rc->low += rc->range;233break;234235case RC_FLUSH:236// Prevent further normalizations.237rc->range = UINT32_MAX;238239// Flush the last five bytes (see rc_flush()).240do {241if (rc_shift_low(rc, out, out_pos, out_size))242return true;243} while (++rc->pos < rc->count);244245// Reset the range encoder so we are ready to continue246// encoding if we weren't finishing the stream.247rc_reset(rc);248return false;249250default:251assert(0);252break;253}254255++rc->pos;256}257258rc->count = 0;259rc->pos = 0;260261return false;262}263264265static inline bool266rc_encode_dummy(const lzma_range_encoder *rc, uint64_t out_limit)267{268assert(rc->count <= RC_SYMBOLS_MAX);269270uint64_t low = rc->low;271uint64_t cache_size = rc->cache_size;272uint32_t range = rc->range;273uint8_t cache = rc->cache;274uint64_t out_pos = rc->out_total;275276size_t pos = rc->pos;277278while (true) {279// Normalize280if (range < RC_TOP_VALUE) {281if (rc_shift_low_dummy(&low, &cache_size, &cache,282&out_pos, out_limit))283return true;284285range <<= RC_SHIFT_BITS;286}287288// This check is here because the normalization above must289// be done before flushing the last bytes.290if (pos == rc->count)291break;292293// Encode a bit294switch (rc->symbols[pos]) {295case RC_BIT_0: {296probability prob = *rc->probs[pos];297range = (range >> RC_BIT_MODEL_TOTAL_BITS)298* prob;299break;300}301302case RC_BIT_1: {303probability prob = *rc->probs[pos];304const uint32_t bound = prob * (range305>> RC_BIT_MODEL_TOTAL_BITS);306low += bound;307range -= bound;308break;309}310311case RC_DIRECT_0:312range >>= 1;313break;314315case RC_DIRECT_1:316range >>= 1;317low += range;318break;319320case RC_FLUSH:321default:322assert(0);323break;324}325326++pos;327}328329// Flush the last bytes. This isn't in rc->symbols[] so we do330// it after the above loop to take into account the size of331// the flushing that will be done at the end of the stream.332for (pos = 0; pos < 5; ++pos) {333if (rc_shift_low_dummy(&low, &cache_size,334&cache, &out_pos, out_limit))335return true;336}337338return false;339}340341342static inline uint64_t343rc_pending(const lzma_range_encoder *rc)344{345return rc->cache_size + 5 - 1;346}347348#endif349350351