Struct constriction::stream::stack::AnsCoder
source · pub struct AnsCoder<Word, State, Backend = Vec<Word>>{ /* private fields */ }
Expand description
Entropy coder for both encoding and decoding on a stack.
This is the generic struct for an ANS coder. It provides fine-tuned control over type
parameters (see discussion in parent
module). You’ll usually
want to use this type through the type alias DefaultAnsCoder
, which provides sane
default settings for the type parameters.
The AnsCoder
uses an entropy coding algorithm called range Asymmetric
Numeral Systems (rANS). This means that it operates as a stack, i.e., a “last
in first out” data structure: encoding “pushes symbols on” the stack and
decoding “pops symbols off” the stack in reverse order. In default operation, decoding
with an AnsCoder
consumes the compressed data for the decoded symbols (however, you
can also decode immutable data by using a Cursor
). This means
that encoding and decoding can be interleaved arbitrarily, thus growing and shrinking
the stack of compressed data as you go.
§Example
Basic usage example:
use constriction::stream::{model::DefaultLeakyQuantizer, stack::DefaultAnsCoder, Decode};
// `DefaultAnsCoder` is a type alias to `AnsCoder` with sane generic parameters.
let mut ans = DefaultAnsCoder::new();
// Create an entropy model based on a quantized Gaussian distribution. You can use `AnsCoder`
// with any entropy model defined in the `models` module.
let quantizer = DefaultLeakyQuantizer::new(-100..=100);
let entropy_model = quantizer.quantize(probability::distribution::Gaussian::new(0.0, 10.0));
let symbols = vec![-10, 4, 0, 3];
// Encode symbols in *reverse* order, so that we can decode them in forward order.
ans.encode_iid_symbols_reverse(&symbols, &entropy_model).unwrap();
// Obtain temporary shared access to the compressed bit string. If you want ownership of the
// compressed bit string, call `.into_compressed()` instead of `.get_compressed()`.
println!("Encoded into {} bits: {:?}", ans.num_bits(), &*ans.get_compressed().unwrap());
// Decode the symbols and verify correctness.
let reconstructed = ans
.decode_iid_symbols(4, &entropy_model)
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(reconstructed, symbols);
§Consistency Between Encoding and Decoding
As elaborated in the parent module’s documentation, encoding and decoding operates on a sequence of symbols. Each symbol can be encoded and decoded with its own entropy model (the symbols can even have heterogeneous types). If your goal is to reconstruct the originally encoded symbols during decoding, then you must employ the same sequence of entropy models (in reversed order) during encoding and decoding.
However, using the same entropy models for encoding and decoding is not a general
requirement. It is perfectly legal to push (encode) symbols on the AnsCoder
using some
entropy models, and then pop off (decode) symbols using different entropy models. The
popped off symbols will then in general be different from the original symbols, but will
be generated in a deterministic way. If there is no deterministic relation between the
entropy models used for pushing and popping, and if there is still compressed data left
at the end (i.e., if is_empty
returns false), then the popped off symbols are, to a
very good approximation, distributed as independent samples from the respective entropy
models. Such random samples, which consume parts of the compressed data, are useful in
the bits-back algorithm.
Implementations§
source§impl<Word, State> AnsCoder<Word, State, Vec<Word>>
impl<Word, State> AnsCoder<Word, State, Vec<Word>>
sourcepub fn new() -> Self
pub fn new() -> Self
Creates an empty ANS entropy coder.
This is usually the starting point if you want to compress data.
§Example
let mut ans = constriction::stream::stack::DefaultAnsCoder::new();
// ... push some symbols onto the ANS coder's stack ...
// Finally, get the compressed data.
let compressed = ans.into_compressed();
§Generality
To avoid type parameters in common use cases, new
is only implemented for
AnsCoder
s with a Vec
backend. To create an empty coder with a different backend,
call Default::default
instead.
source§impl<Word, State, Backend> AnsCoder<Word, State, Backend>
impl<Word, State, Backend> AnsCoder<Word, State, Backend>
sourcepub fn from_raw_parts(bulk: Backend, state: State) -> Self
pub fn from_raw_parts(bulk: Backend, state: State) -> Self
Low-level constructor that assembles an AnsCoder
from its internal components.
The arguments bulk
and state
correspond to the two return values of the method
into_raw_parts
.
The caller must ensure that state >= State::one() << (State::BITS - Word::BITS)
unless bulk
is empty. This cannot be checked by the method since not all
Backend
s have an is_empty
method. Violating this invariant is not a memory
safety issue but it will lead to incorrect behavior.
sourcepub fn from_compressed(compressed: Backend) -> Result<Self, Backend>
pub fn from_compressed(compressed: Backend) -> Result<Self, Backend>
Creates an ANS stack with some initial compressed data.
This is usually the starting point if you want to decompress data previously
obtained from into_compressed
. However, it can also be used to append more
symbols to an existing compressed buffer of data.
Returns Err(compressed)
if compressed
is not empty and its last entry is
zero, since an AnsCoder
cannot represent trailing zero words. This error cannot
occur if compressed
was obtained from into_compressed
, which never returns
data with a trailing zero word. If you want to construct a AnsCoder
from an
unknown source of binary data (e.g., to decode some side information into latent
variables) then call from_binary
instead.
sourcepub fn from_binary(data: Backend) -> Result<Self, Backend::ReadError>
pub fn from_binary(data: Backend) -> Result<Self, Backend::ReadError>
Like from_compressed
but works on any binary data.
This method is meant for rather advanced use cases. For most common use cases,
you probably want to call from_compressed
instead.
Different to from_compressed
, this method also works if data
ends in a zero
word. Calling this method is equivalent to (but likely more efficient than)
appending a 1
word to data
and then calling from_compressed
. Note that
therefore, this method always constructs a non-empty AnsCoder
(even if data
is
empty):
use constriction::stream::stack::DefaultAnsCoder;
let stack1 = DefaultAnsCoder::from_binary(Vec::new()).unwrap();
assert!(!stack1.is_empty()); // <-- stack1 is *not* empty.
let stack2 = DefaultAnsCoder::from_compressed(Vec::new()).unwrap();
assert!(stack2.is_empty()); // <-- stack2 is empty.
pub fn bulk(&self) -> &Backend
sourcepub fn into_raw_parts(self) -> (Backend, State)
pub fn into_raw_parts(self) -> (Backend, State)
Low-level method that disassembles the AnsCoder
into its internal components.
Can be used together with from_raw_parts
.
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Check if no data for decoding is left.
Note that you can still pop symbols off an empty stack, but this is only
useful in rare edge cases, see documentation of
decode_symbol
.
sourcepub fn get_compressed(
&mut self,
) -> Result<impl Deref<Target = Backend> + Debug + Drop + '_, Backend::WriteError>
pub fn get_compressed( &mut self, ) -> Result<impl Deref<Target = Backend> + Debug + Drop + '_, Backend::WriteError>
Assembles the current compressed data into a single slice.
Returns the concatenation of bulk
and state
. The concatenation truncates
any trailing zero words, which is compatible with the constructor
from_compressed
.
This method requires a &mut self
receiver to temporarily append state
to
bulk
(this mutationwill be reversed to recreate the original bulk
as soon as
the caller drops the returned value). If you don’t have mutable access to the
AnsCoder
, consider calling iter_compressed
instead, or get the bulk
and
state
separately by calling bulk
and state
, respectively.
The return type dereferences to &[Word]
, thus providing read-only
access to the compressed data. If you need ownership of the compressed data,
consider calling into_compressed
instead.
§Example
use constriction::stream::{
model::DefaultContiguousCategoricalEntropyModel, stack::DefaultAnsCoder, Decode
};
let mut ans = DefaultAnsCoder::new();
// Push some data on the ans.
let symbols = vec![8, 2, 0, 7];
let probabilities = vec![0.03, 0.07, 0.1, 0.1, 0.2, 0.2, 0.1, 0.15, 0.05];
let model = DefaultContiguousCategoricalEntropyModel
::from_floating_point_probabilities_fast(&probabilities, None).unwrap();
ans.encode_iid_symbols_reverse(&symbols, &model).unwrap();
// Inspect the compressed data.
dbg!(ans.get_compressed());
// We can still use the ANS coder afterwards.
let reconstructed = ans
.decode_iid_symbols(4, &model)
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(reconstructed, symbols);
pub fn get_binary( &mut self, ) -> Result<impl Deref<Target = Backend> + Debug + Drop + '_, CoderError<(), Backend::WriteError>>
sourcepub fn iter_compressed<'a>(&'a self) -> impl Iterator<Item = Word> + '_
pub fn iter_compressed<'a>(&'a self) -> impl Iterator<Item = Word> + '_
Iterates over the compressed data currently on the ans.
In contrast to get_compressed
or into_compressed
, this method does
not require mutable access or even ownership of the AnsCoder
.
§Example
use constriction::stream::{model::DefaultLeakyQuantizer, stack::DefaultAnsCoder, Decode};
// Create a stack and encode some stuff.
let mut ans = DefaultAnsCoder::new();
let symbols = vec![8, -12, 0, 7];
let quantizer = DefaultLeakyQuantizer::new(-100..=100);
let model =
quantizer.quantize(probability::distribution::Gaussian::new(0.0, 10.0));
ans.encode_iid_symbols_reverse(&symbols, &model).unwrap();
// Iterate over compressed data, collect it into to a Vec``, and compare to direct method.
let compressed_iter = ans.iter_compressed();
let compressed_collected = compressed_iter.collect::<Vec<_>>();
assert!(!compressed_collected.is_empty());
assert_eq!(compressed_collected, *ans.get_compressed().unwrap());
sourcepub fn num_words(&self) -> usizewhere
Backend: BoundedReadWords<Word, Stack>,
pub fn num_words(&self) -> usizewhere
Backend: BoundedReadWords<Word, Stack>,
Returns the number of compressed words on the ANS coder’s stack.
This includes a constant overhead of between one and two words unless the stack is completely empty.
This method returns the length of the slice, the Vec<Word>
, or the iterator
that would be returned by get_compressed
, into_compressed
, or
iter_compressed
, respectively, when called at this time.
See also num_bits
.
pub fn num_bits(&self) -> usizewhere
Backend: BoundedReadWords<Word, Stack>,
pub fn num_valid_bits(&self) -> usizewhere
Backend: BoundedReadWords<Word, Stack>,
pub fn into_decoder(self) -> AnsCoder<Word, State, Backend::IntoReadWords>where
Backend: IntoReadWords<Word, Stack>,
sourcepub fn into_seekable_decoder(
self,
) -> AnsCoder<Word, State, Backend::IntoSeekReadWords>where
Backend: IntoSeekReadWords<Word, Stack>,
pub fn into_seekable_decoder(
self,
) -> AnsCoder<Word, State, Backend::IntoSeekReadWords>where
Backend: IntoSeekReadWords<Word, Stack>,
Consumes the AnsCoder
and returns a decoder that implements Seek
.
This method is similar to as_seekable_decoder
except that it takes ownership of
the original AnsCoder
, so the returned seekable decoder can typically be returned
from the calling function or put on the heap.
pub fn as_decoder<'a>(&'a self) -> AnsCoder<Word, State, Backend::AsReadWords>where
Backend: AsReadWords<'a, Word, Stack>,
sourcepub fn as_seekable_decoder<'a>(
&'a self,
) -> AnsCoder<Word, State, Backend::AsSeekReadWords>where
Backend: AsSeekReadWords<'a, Word, Stack>,
pub fn as_seekable_decoder<'a>(
&'a self,
) -> AnsCoder<Word, State, Backend::AsSeekReadWords>where
Backend: AsSeekReadWords<'a, Word, Stack>,
Returns a decoder that implements Seek
.
The returned decoder shares access to the compressed data with the original
AnsCoder
(i.e., self
). This means that:
- you can call this method several times to create several seekable decoders with independent views into the same compressed data;
- once the lifetime of all handed out seekable decoders ends, the original
AnsCoder
can be used again; and - the constructed seekable decoder cannot outlive the original
AnsCoder
; for example, if the originalAnsCoder
lives on the calling function’s call stack frame then you cannot return the constructed seekable decoder from the calling function. If this is a problem then callinto_seekable_decoder
instead.
§Limitations
TODO: this text is outdated.
This method is only implemented for AnsCoder
s whose backing store of compressed
data (Backend
) implements AsRef<[Word]>
. This includes the default
backing data store Backend = Vec<Word>
.
source§impl<Word, State> AnsCoder<Word, State>
impl<Word, State> AnsCoder<Word, State>
sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Discards all compressed data and resets the coder to the same state as
Coder::new
.
source§impl<'bulk, Word, State> AnsCoder<Word, State, Cursor<Word, &'bulk [Word]>>
impl<'bulk, Word, State> AnsCoder<Word, State, Cursor<Word, &'bulk [Word]>>
pub fn from_compressed_slice(compressed: &'bulk [Word]) -> Result<Self, ()>
pub fn from_binary_slice(data: &'bulk [Word]) -> Self
source§impl<Word, State, Buf> AnsCoder<Word, State, Reverse<Cursor<Word, Buf>>>
impl<Word, State, Buf> AnsCoder<Word, State, Reverse<Cursor<Word, Buf>>>
pub fn from_reversed_compressed(compressed: Buf) -> Result<Self, Buf>
pub fn from_reversed_binary(data: Buf) -> Self
source§impl<Word, State, Iter, ReadError> AnsCoder<Word, State, FallibleIteratorReadWords<Iter>>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Iter: Iterator<Item = Result<Word, ReadError>>,
FallibleIteratorReadWords<Iter>: ReadWords<Word, Stack, ReadError = ReadError>,
impl<Word, State, Iter, ReadError> AnsCoder<Word, State, FallibleIteratorReadWords<Iter>>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Iter: Iterator<Item = Result<Word, ReadError>>,
FallibleIteratorReadWords<Iter>: ReadWords<Word, Stack, ReadError = ReadError>,
pub fn from_reversed_compressed_iter( compressed: Iter, ) -> Result<Self, Fuse<Iter>>
pub fn from_reversed_binary_iter(data: Iter) -> Result<Self, ReadError>
source§impl<Word, State, Backend> AnsCoder<Word, State, Backend>
impl<Word, State, Backend> AnsCoder<Word, State, Backend>
pub fn encode_symbols_reverse<S, M, I, const PRECISION: usize>(
&mut self,
symbols_and_models: I,
) -> Result<(), CoderError<DefaultEncoderFrontendError, Backend::WriteError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Word>,
Word: AsPrimitive<M::Probability>,
I: IntoIterator<Item = (S, M)>,
I::IntoIter: DoubleEndedIterator,
pub fn try_encode_symbols_reverse<S, M, E, I, const PRECISION: usize>(
&mut self,
symbols_and_models: I,
) -> Result<(), TryCodingError<CoderError<DefaultEncoderFrontendError, Backend::WriteError>, E>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Word>,
Word: AsPrimitive<M::Probability>,
I: IntoIterator<Item = Result<(S, M), E>>,
I::IntoIter: DoubleEndedIterator,
pub fn encode_iid_symbols_reverse<S, M, I, const PRECISION: usize>(
&mut self,
symbols: I,
model: M,
) -> Result<(), CoderError<DefaultEncoderFrontendError, Backend::WriteError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION> + Copy,
M::Probability: Into<Word>,
Word: AsPrimitive<M::Probability>,
I: IntoIterator<Item = S>,
I::IntoIter: DoubleEndedIterator,
sourcepub fn into_compressed(self) -> Result<Backend, Backend::WriteError>
pub fn into_compressed(self) -> Result<Backend, Backend::WriteError>
Consumes the ANS coder and returns the compressed data.
The returned data can be used to recreate an ANS coder with the same state
(e.g., for decoding) by passing it to
from_compressed
.
If you don’t want to consume the ANS coder, consider calling
get_compressed
,
iter_compressed
instead.
§Example
use constriction::stream::{
model::DefaultContiguousCategoricalEntropyModel, stack::DefaultAnsCoder, Decode
};
let mut ans = DefaultAnsCoder::new();
// Push some data onto the ANS coder's stack:
let symbols = vec![8, 2, 0, 7];
let probabilities = vec![0.03, 0.07, 0.1, 0.1, 0.2, 0.2, 0.1, 0.15, 0.05];
let model = DefaultContiguousCategoricalEntropyModel
::from_floating_point_probabilities_fast(&probabilities, None).unwrap();
ans.encode_iid_symbols_reverse(&symbols, &model).unwrap();
// Get the compressed data, consuming the ANS coder:
let compressed = ans.into_compressed().unwrap();
// ... write `compressed` to a file and then read it back later ...
// Create a new ANS coder with the same state and use it for decompression:
let mut ans = DefaultAnsCoder::from_compressed(compressed).expect("Corrupted compressed file.");
let reconstructed = ans
.decode_iid_symbols(4, &model)
.collect::<Result<Vec<_>, _>>()
.unwrap();
assert_eq!(reconstructed, symbols);
assert!(ans.is_empty())
sourcepub fn into_binary(self) -> Result<Backend, Option<Backend::WriteError>>
pub fn into_binary(self) -> Result<Backend, Option<Backend::WriteError>>
Returns the binary data if it fits precisely into an integer number of
Word
s
This method is meant for rather advanced use cases. For most common use cases,
you probably want to call into_compressed
instead.
This method is the inverse of from_binary
. It is equivalent to calling
into_compressed
, verifying that the returned vector ends in a 1
word, and
popping off that trailing 1
word.
Returns Err(())
if the compressed data (excluding an obligatory trailing
1
bit) does not fit into an integer number of Word
s. This error
case includes the case of an empty AnsCoder
(since an empty AnsCoder
lacks the
obligatory trailing one-bit).
§Example
// Some binary data we want to represent on a `AnsCoder`.
let data = vec![0x89ab_cdef, 0x0123_4567];
// Constructing a `AnsCoder` with `from_binary` indicates that all bits of `data` are
// considered part of the information-carrying payload.
let stack1 = constriction::stream::stack::DefaultAnsCoder::from_binary(data.clone()).unwrap();
assert_eq!(stack1.clone().into_binary().unwrap(), data); // <-- Retrieves the original `data`.
// By contrast, if we construct a `AnsCoder` with `from_compressed`, we indicate that
// - any leading `0` bits of the last entry of `data` are not considered part of
// the information-carrying payload; and
// - the (obligatory) first `1` bit of the last entry of `data` defines the
// boundary between unused bits and information-carrying bits; it is therefore
// also not considered part of the payload.
// Therefore, `stack2` below only contains `32 * 2 - 7 - 1 = 56` bits of payload,
// which cannot be exported into an integer number of `u32` words:
let stack2 = constriction::stream::stack::DefaultAnsCoder::from_compressed(data.clone()).unwrap();
assert!(stack2.clone().into_binary().is_err()); // <-- Returns an error.
// Use `into_compressed` to retrieve the data in this case:
assert_eq!(stack2.into_compressed().unwrap(), data);
// Calling `into_compressed` on `stack1` would append an extra `1` bit to indicate
// the boundary between information-carrying bits and padding `0` bits:
assert_eq!(stack1.into_compressed().unwrap(), vec![0x89ab_cdef, 0x0123_4567, 0x0000_0001]);
Trait Implementations§
source§impl<'a, Word, State, Backend, const PRECISION: usize> AsDecoder<'a, PRECISION> for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: WriteWords<Word> + AsReadWords<'a, Word, Stack>,
impl<'a, Word, State, Backend, const PRECISION: usize> AsDecoder<'a, PRECISION> for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: WriteWords<Word> + AsReadWords<'a, Word, Stack>,
source§type AsDecoder = AnsCoder<Word, State, <Backend as AsReadWords<'a, Word, Stack>>::AsReadWords>
type AsDecoder = AnsCoder<Word, State, <Backend as AsReadWords<'a, Word, Stack>>::AsReadWords>
source§fn as_decoder(&'a self) -> Self::AsDecoder
fn as_decoder(&'a self) -> Self::AsDecoder
source§impl<Word, State, Backend> Code for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> Code for AnsCoder<Word, State, Backend>
source§type Word = Word
type Word = Word
Word
per symbol (plus a constant
overhead).source§impl<Word, State, Backend> Debug for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
for<'a> &'a Backend: IntoIterator<Item = &'a Word>,
impl<Word, State, Backend> Debug for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
for<'a> &'a Backend: IntoIterator<Item = &'a Word>,
source§impl<Word, State, Backend, const PRECISION: usize> Decode<PRECISION> for AnsCoder<Word, State, Backend>
impl<Word, State, Backend, const PRECISION: usize> Decode<PRECISION> for AnsCoder<Word, State, Backend>
source§type FrontendError = Infallible
type FrontendError = Infallible
ANS coding is surjective, and we (deliberately) allow decoding past EOF (in a deterministic way) for consistency. Therefore, decoding cannot fail.
source§fn decode_symbol<M>(
&mut self,
model: M,
) -> Result<M::Symbol, CoderError<Self::FrontendError, Self::BackendError>>where
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn decode_symbol<M>(
&mut self,
model: M,
) -> Result<M::Symbol, CoderError<Self::FrontendError, Self::BackendError>>where
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
Decodes a single symbol and pops it off the compressed data.
This is a low level method. You usually probably want to call a batch method
like decode_symbols
or
decode_iid_symbols
instead.
This method is called decode_symbol
rather than decode_symbol
to stress the
fact that the AnsCoder
is a stack: decode_symbol
will return the last symbol
that was previously encoded via encode_symbol
.
Note that this method cannot fail. It will still produce symbols in a deterministic way even if the stack is empty, but such symbols will not recover any previously encoded data and will generally have low entropy. Still, being able to pop off an arbitrary number of symbols can sometimes be useful in edge cases of, e.g., the bits-back algorithm.
source§type BackendError = <Backend as ReadWords<Word, Stack>>::ReadError
type BackendError = <Backend as ReadWords<Word, Stack>>::ReadError
source§fn maybe_exhausted(&self) -> bool
fn maybe_exhausted(&self) -> bool
source§fn decode_symbols<'s, I, M>(
&'s mut self,
models: I,
) -> DecodeSymbols<'s, Self, I::IntoIter, PRECISION> ⓘwhere
I: IntoIterator<Item = M> + 's,
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn decode_symbols<'s, I, M>(
&'s mut self,
models: I,
) -> DecodeSymbols<'s, Self, I::IntoIter, PRECISION> ⓘwhere
I: IntoIterator<Item = M> + 's,
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
source§fn try_decode_symbols<'s, I, M, E>(
&'s mut self,
models: I,
) -> TryDecodeSymbols<'s, Self, I::IntoIter, PRECISION> ⓘwhere
I: IntoIterator<Item = Result<M, E>> + 's,
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn try_decode_symbols<'s, I, M, E>(
&'s mut self,
models: I,
) -> TryDecodeSymbols<'s, Self, I::IntoIter, PRECISION> ⓘwhere
I: IntoIterator<Item = Result<M, E>> + 's,
M: DecoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
source§fn decode_iid_symbols<M>(
&mut self,
amt: usize,
model: M,
) -> DecodeIidSymbols<'_, Self, M, PRECISION> ⓘwhere
M: DecoderModel<PRECISION> + Copy,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn decode_iid_symbols<M>(
&mut self,
amt: usize,
model: M,
) -> DecodeIidSymbols<'_, Self, M, PRECISION> ⓘwhere
M: DecoderModel<PRECISION> + Copy,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
amt
symbols using the same entropy model for all symbols. Read moresource§impl<Word, State, Backend, const PRECISION: usize> Encode<PRECISION> for AnsCoder<Word, State, Backend>
impl<Word, State, Backend, const PRECISION: usize> Encode<PRECISION> for AnsCoder<Word, State, Backend>
source§fn encode_symbol<M>(
&mut self,
symbol: impl Borrow<M::Symbol>,
model: M,
) -> Result<(), CoderError<DefaultEncoderFrontendError, Self::BackendError>>where
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn encode_symbol<M>(
&mut self,
symbol: impl Borrow<M::Symbol>,
model: M,
) -> Result<(), CoderError<DefaultEncoderFrontendError, Self::BackendError>>where
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
Encodes a single symbol and appends it to the compressed data.
This is a low level method. You probably usually want to call a batch method
like encode_symbols
or
encode_iid_symbols
instead. See examples there.
The bound impl Borrow<M::Symbol>
on argument symbol
essentially means that
you can provide the symbol either by value or by reference, at your choice.
Returns Err(ImpossibleSymbol)
if symbol
has zero probability under the
entropy model model
. This error can usually be avoided by using a
“leaky” distribution as the entropy model, i.e., a distribution that assigns a
nonzero probability to all symbols within a finite domain. Leaky distributions
can be constructed with, e.g., a
LeakyQuantizer
or with
LeakyCategorical::from_floating_point_probabilities
.
TODO: move this and similar doc comments to the trait definition.
source§type FrontendError = DefaultEncoderFrontendError
type FrontendError = DefaultEncoderFrontendError
source§type BackendError = <Backend as WriteWords<Word>>::WriteError
type BackendError = <Backend as WriteWords<Word>>::WriteError
source§fn maybe_full(&self) -> bool
fn maybe_full(&self) -> bool
source§fn encode_symbols<S, M>(
&mut self,
symbols_and_models: impl IntoIterator<Item = (S, M)>,
) -> Result<(), CoderError<Self::FrontendError, Self::BackendError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn encode_symbols<S, M>(
&mut self,
symbols_and_models: impl IntoIterator<Item = (S, M)>,
) -> Result<(), CoderError<Self::FrontendError, Self::BackendError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
source§fn try_encode_symbols<S, M, E>(
&mut self,
symbols_and_models: impl IntoIterator<Item = Result<(S, M), E>>,
) -> Result<(), TryCodingError<CoderError<Self::FrontendError, Self::BackendError>, E>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn try_encode_symbols<S, M, E>(
&mut self,
symbols_and_models: impl IntoIterator<Item = Result<(S, M), E>>,
) -> Result<(), TryCodingError<CoderError<Self::FrontendError, Self::BackendError>, E>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION>,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
source§fn encode_iid_symbols<S, M>(
&mut self,
symbols: impl IntoIterator<Item = S>,
model: M,
) -> Result<(), CoderError<Self::FrontendError, Self::BackendError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION> + Copy,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
fn encode_iid_symbols<S, M>(
&mut self,
symbols: impl IntoIterator<Item = S>,
model: M,
) -> Result<(), CoderError<Self::FrontendError, Self::BackendError>>where
S: Borrow<M::Symbol>,
M: EncoderModel<PRECISION> + Copy,
M::Probability: Into<Self::Word>,
Self::Word: AsPrimitive<M::Probability>,
source§impl<'a, Word, State, Backend> From<&'a AnsCoder<Word, State, Backend>> for AnsCoder<Word, State, <Backend as AsReadWords<'a, Word, Stack>>::AsReadWords>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: AsReadWords<'a, Word, Stack>,
impl<'a, Word, State, Backend> From<&'a AnsCoder<Word, State, Backend>> for AnsCoder<Word, State, <Backend as AsReadWords<'a, Word, Stack>>::AsReadWords>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: AsReadWords<'a, Word, Stack>,
source§impl<Word, State, Backend, const PRECISION: usize> IntoDecoder<PRECISION> for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: WriteWords<Word> + IntoReadWords<Word, Stack>,
impl<Word, State, Backend, const PRECISION: usize> IntoDecoder<PRECISION> for AnsCoder<Word, State, Backend>where
Word: BitArray + Into<State>,
State: BitArray + AsPrimitive<Word>,
Backend: WriteWords<Word> + IntoReadWords<Word, Stack>,
source§type IntoDecoder = AnsCoder<Word, State, <Backend as IntoReadWords<Word, Stack>>::IntoReadWords>
type IntoDecoder = AnsCoder<Word, State, <Backend as IntoReadWords<Word, Stack>>::IntoReadWords>
source§fn into_decoder(self) -> Self::IntoDecoder
fn into_decoder(self) -> Self::IntoDecoder
Auto Trait Implementations§
impl<Word, State, Backend> Freeze for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> RefUnwindSafe for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> Send for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> Sync for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> Unpin for AnsCoder<Word, State, Backend>
impl<Word, State, Backend> UnwindSafe for AnsCoder<Word, State, Backend>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)