/*Takes updated low and range values, renormalizes them so that 32768<=rng<65536(flushingbytesfromlowtotheoutputbufferif necessary),andstoresthembackintheencodercontext. low:Thenewvalueoflow.
rng: The new value of the range.*/ staticvoid od_ec_enc_normalize(od_ec_enc *enc, od_ec_enc_window low, unsigned rng) { int d; int c; int s; if (enc->error) return;
c = enc->cnt;
assert(rng <= 65535U); /*The number of leading zeros in the 16-bit binary representation of rng.*/
d = 16 - OD_ILOG_NZ(rng);
s = c + d;
/* We flush every time "low" cannot safely and efficiently accommodate any moredata.Overall,cmustnotexceed63atthetimeofbyteflushout.To facilitatethis,"s"cannotexceed56-bitsbecausewehavetokeep1byte forcarry.Also,weneedtosubtract16becausewewanttokeeproomfor thenextsymbolworth"d"-bits(max15).Analternateconditionwouldbeif (e<d),wheree=numberofleadingzerosin"low",indicatingthereis notenoughrooomtoaccommodate"rng"worthof"d"-bitsin"low".However, thisapproachneedsadditionalcomputations:(i)compute"e",(ii)push theleading0x00'sasaspecialcase.
*/ if (s >= 40) { // 56 - 16 unsignedchar *out = enc->buf;
uint32_t storage = enc->storage;
uint32_t offs = enc->offs; if (offs + 8 > storage) {
storage = 2 * storage + 8;
out = (unsignedchar *)realloc(out, sizeof(*out) * storage); if (out == NULL) {
enc->error = -1; return;
}
enc->buf = out;
enc->storage = storage;
} // Need to add 1 byte here since enc->cnt always counts 1 byte less // (enc->cnt = -9) to ensure correct operation
uint8_t num_bytes_ready = (s >> 3) + 1;
// Update "c" to contain the number of non-ready bits in "low". Since "low" // has 64-bit capacity, we need to add the (64 - 40) cushion bits and take // off the number of ready bits.
c += 24 - (num_bytes_ready << 3);
// Prepare data and carry mask
uint64_t mask = (uint64_t)1 << (num_bytes_ready << 3);
uint64_t carry = output & mask;
mask = mask - 0x01;
output = output & mask;
// Write data in a single operation
write_enc_data_to_out_buf(out, offs, output, carry, &enc->offs,
num_bytes_ready);
// Update state of the encoder: enc->cnt to contain the number of residual // bits
s = c + d - 24;
}
enc->low = low << d;
enc->rng = rng << d;
enc->cnt = s;
}
/*Initializes the encoder.
size: The initial size of the buffer, in bytes.*/ void od_ec_enc_init(od_ec_enc *enc, uint32_t size) {
od_ec_enc_reset(enc);
enc->buf = (unsignedchar *)malloc(sizeof(*enc->buf) * size);
enc->storage = size; if (size > 0 && enc->buf == NULL) {
enc->storage = 0;
enc->error = -1;
}
}
/*Reinitializes the encoder.*/ void od_ec_enc_reset(od_ec_enc *enc) {
enc->offs = 0;
enc->low = 0;
enc->rng = 0x8000; /*This is initialized to -9 so that it crosses zero after we've accumulated
one byte + one carry bit.*/
enc->cnt = -9;
enc->error = 0; #if OD_MEASURE_EC_OVERHEAD
enc->entropy = 0;
enc->nb_symbols = 0; #endif
}
/*Frees the buffers used by the encoder.*/ void od_ec_enc_clear(od_ec_enc *enc) { free(enc->buf); }
/*Encodes a symbol given its frequency in Q15. fl:CDF_PROB_TOPminusthecumulativefrequencyofallsymbolsthatcome beforetheonetobeencoded. fh:CDF_PROB_TOPminusthecumulativefrequencyofallsymbolsuptoand
including the one to be encoded.*/ staticvoid od_ec_encode_q15(od_ec_enc *enc, unsigned fl, unsigned fh, int s, int nsyms) {
od_ec_enc_window l; unsigned r; unsigned u; unsigned v;
l = enc->low;
r = enc->rng;
assert(32768U <= r);
assert(fh <= fl);
assert(fl <= 32768U);
assert(7 - EC_PROB_SHIFT >= 0); constint N = nsyms - 1; if (fl < CDF_PROB_TOP) {
u = ((r >> 8) * (uint32_t)(fl >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) +
EC_MIN_PROB * (N - (s - 1));
v = ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) +
EC_MIN_PROB * (N - (s + 0));
l += r - u;
r = u - v;
} else {
r -= ((r >> 8) * (uint32_t)(fh >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT)) +
EC_MIN_PROB * (N - (s + 0));
}
od_ec_enc_normalize(enc, l, r); #if OD_MEASURE_EC_OVERHEAD
enc->entropy -= OD_LOG2((double)(OD_ICDF(fh) - OD_ICDF(fl)) / CDF_PROB_TOP.);
enc->nb_symbols++; #endif
}
/*Encode a single binary value. val:Thevaluetoencode(0or1).
f: The probability that the val is one, scaled by 32768.*/ void od_ec_encode_bool_q15(od_ec_enc *enc, int val, unsigned f) {
od_ec_enc_window l; unsigned r; unsigned v;
assert(0 < f);
assert(f < 32768U);
l = enc->low;
r = enc->rng;
assert(32768U <= r);
v = ((r >> 8) * (uint32_t)(f >> EC_PROB_SHIFT) >> (7 - EC_PROB_SHIFT));
v += EC_MIN_PROB; if (val) l += r - v;
r = val ? v : r - v;
od_ec_enc_normalize(enc, l, r); #if OD_MEASURE_EC_OVERHEAD
enc->entropy -= OD_LOG2((double)(val ? f : (32768 - f)) / 32768.);
enc->nb_symbols++; #endif
}
/*Encodes a symbol given a cumulative distribution function (CDF) table in Q15. s:Theindexofthesymboltoencode. icdf:32768minustheCDF,suchthatsymbolsfallsintherange [s>0?(32768-icdf[s-1]):0,32768-icdf[s]). Thevaluesmustbemonotonicallydecreasing,andicdf[nsyms-1]must be0. nsyms:Thenumberofsymbolsinthealphabet.
This should be at most 16.*/ void od_ec_encode_cdf_q15(od_ec_enc *enc, int s, const uint16_t *icdf, int nsyms) {
(void)nsyms;
assert(s >= 0);
assert(s < nsyms);
assert(icdf[nsyms - 1] == OD_ICDF(CDF_PROB_TOP));
od_ec_encode_q15(enc, s > 0 ? icdf[s - 1] : OD_ICDF(0), icdf[s], s, nsyms);
}
/*Indicates that there are no more symbols to encode. Allremainingoutputbytesareflushedtotheoutputbuffer. od_ec_enc_reset()shouldbecalledbeforeusingtheencoderagain. bytes:Returnsthesizeoftheencodeddatainthereturnedbuffer. Return:Apointertothestartofthefinalbuffer,orNULLiftherewasan
encoding error.*/ unsignedchar *od_ec_enc_done(od_ec_enc *enc, uint32_t *nbytes) { unsignedchar *out;
uint32_t storage;
uint32_t offs;
od_ec_enc_window m;
od_ec_enc_window e;
od_ec_enc_window l; int c; int s; if (enc->error) return NULL; #if OD_MEASURE_EC_OVERHEAD
{
uint32_t tell; /* Don't count the 1 bit we lose to raw bits as overhead. */
tell = od_ec_enc_tell(enc) - 1;
fprintf(stderr, "overhead: %f%%\n", 100 * (tell - enc->entropy) / enc->entropy);
fprintf(stderr, "efficiency: %f bits/symbol\n",
(double)tell / enc->nb_symbols);
} #endif
l = enc->low;
c = enc->cnt;
s = 10;
m = 0x3FFF;
e = ((l + m) & ~m) | (m + 1);
s += c;
offs = enc->offs;
/*Make sure there's enough room for the entropy-coded bits.*/
out = enc->buf;
storage = enc->storage; constint s_bits = (s + 7) >> 3; int b = OD_MAXI(s_bits, 0); if (offs + b > storage) {
storage = offs + b;
out = (unsignedchar *)realloc(out, sizeof(*out) * storage); if (out == NULL) {
enc->error = -1; return NULL;
}
enc->buf = out;
enc->storage = storage;
}
/*We output the minimum number of bits that ensures that the symbols encoded
thus far will be decoded correctly regardless of the bits that follow.*/ if (s > 0) {
uint64_t n;
n = ((uint64_t)1 << (c + 16)) - 1; do {
assert(offs < storage);
uint16_t val = (uint16_t)(e >> (c + 16));
out[offs] = (unsignedchar)(val & 0x00FF); if (val & 0x0100) {
assert(offs > 0);
propagate_carry_bwd(out, offs - 1);
}
offs++;
e &= n;
s -= 8;
c -= 8;
n >>= 8;
} while (s > 0);
}
*nbytes = offs;
return out;
}
/*Returns the number of bits "used" by the encoded symbols so far. Thissamenumbercanbecomputedineithertheencoderorthedecoder,andis suitableformakingcodingdecisions. Warning:Thevaluereturnedbythisfunctioncandecreasecomparedtoan earliercall,evenafterencodingmoredata,ifthereisanencodingerror (i.e.,afailuretoallocateenoughspacefortheoutputbuffer). Return:Thenumberofbits. Thiswillalwaysbeslightlylargerthantheexactvalue(e.g.,all
rounding error is in the positive direction).*/ int od_ec_enc_tell(const od_ec_enc *enc) { /*The 10 here counteracts the offset of -9 baked into cnt, and adds 1 extra
bit, which we reserve for terminating the stream.*/ return (enc->cnt + 10) + enc->offs * 8;
}
/*Returns the number of bits "used" by the encoded symbols so far. Thissamenumbercanbecomputedineithertheencoderorthedecoder,andis suitableformakingcodingdecisions. Warning:Thevaluereturnedbythisfunctioncandecreasecomparedtoan earliercall,evenafterencodingmoredata,ifthereisanencodingerror (i.e.,afailuretoallocateenoughspacefortheoutputbuffer). Return:Thenumberofbitsscaledby2**OD_BITRES. Thiswillalwaysbeslightlylargerthantheexactvalue(e.g.,all
rounding error is in the positive direction).*/
uint32_t od_ec_enc_tell_frac(const od_ec_enc *enc) { return od_ec_tell_frac(od_ec_enc_tell(enc), enc->rng);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.18 Sekunden
(vorverarbeitet am 2026-08-24)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.