ryg_rans is not a library | The ryg blog
Skip to content
Follow:<br>RSS<br>Twitter
The ryg blog
When I grow up I'll be an inventor.
Home
About
Coding
Compression
Computer Architecture
Demoscene
Graphics Pipeline
Maths
Multimedia
Networking
Papers
Stories
Thoughts
Uncategorized
ryg_rans is not a library
August 3, 2026
I wrote ryg_rans in 2014. I still regularly get questions and patch submissions from people who want to use it as a library. That is not what it’s for!
ryg_rans is not a library, never was. It’s a toy implementation of an algorithm whose core fits in something like 20 lines of code. It’s the equivalent of the wooden board you sometimes see in hardware stores where they have 30 different types and sizes of fasteners screwed, bolted or nailed in. The idea is not that you should use this in your builds; it’s a visual aid to show you the options available to you. A real project should pick one, or maybe two, options and stick with it.
You should not be using ryg_rans itself for anything. Its goal is to be a small example accompanying my writings on the subject, not to be a rANS encoding/decoding library. It is exceptionally bad at the latter. It is neither particularly optimized for speed (and, indeed, not fast, not even the SIMD versions – they are meant to show the idea, not to be used in production, and are appreciably worse than "proper" implementations), nor robust, nor "batteries included", and the static model included in the code makes no sense to use with rANS, you would just use tANS instead. The only reason the static byte model is in there is because the code needed something to be a working implementation, and fully static byte-granular, although pointless, is the easiest model.
Our actual uses of rANS in codecs like Oodle LZNA use either the fully adaptive "exponential moving average"-type models described in https://fgiesen.wordpress.com/2015/05/26/models-for-adaptive-arithmetic-coding/ or a semi-static model based on running counts that is updated every few hundred symbols in BitKnit. Some more details in https://fgiesen.wordpress.com/2023/05/06/a-very-brief-bitknit-retrospective/.
Something like the alias table variant is cute but I would strongly advise against ever including it in any production bitstream because there is simply no case I can think of where it’s ever actually a good idea. I wrote it up because I thought it was interesting and that maybe I would come up with a compelling use case for it at some point, but it’s been 12 years and I’m still waiting. The alias encoding requires considerable-size extra tables in the encoder, still forces you into mostly-static models (which loses the main advantage of rANS), and is slow to both encode and decode. If you have a static distribution, tANS/FSE is almost always preferable.
Similarly, do not use multiple encoding/interleaving variants based on SIMD ISA availability in the same bitstream. That is a terrible idea. Again, ryg_rans is a toy example meant to illustrate the ideas in that design space, not a blueprint for a library. If you design a format or actual library, you have to make a choice. Bitstreams are forever, or as near as makes no difference. One of the fundamental problems with all interleaved ANS variants is that the number of interleaved streams is a "magic constant" that significantly constrains implementations. The "sweet spot" is very different between types of machines and microarchitectures, to the extent that e.g. there is no literally overlap between stream counts that make sense for something like a low-end 32-bit ARM microcontroller (like the Cortex M series) and say a GPU.
Having lots of variants in the same bitstream makes everything worse. Now, instead of one encoding that is good for some targets and bad for others, you have multiple encodings, multiple times the code complexity and attack surface, and for every target and application there is usually only one "good" choice of interleaving.
More to the point, an unintended side effect of the static byte models in the examples is that it skews things towards much higher interleave factors that are not actually sustainable in use cases where rANS makes sense. If you use any kind of adaptive model, as you should, because that is the main reason to use rANS, the practical degree of interleaving you can attain is usually limited by the number of independent model updates you can actually sustain before you get back to a model that has an update pending, and that number is frequently something like 2 or 3. While it is true that something like rANS can in principle use very large interleave factors, it is unfortunately not something that makes sense in most practical implementations because of the modeling limitations.
Which brings me to the final point: with rANS, same as with arithmetic encoders, probability modeling and the actual encoding are almost alway intertwined. The static byte model makes it so the two are actually...