One area that I’ve always found problematic in Lua is its number type. It’s a one size fits all solution and there are things I want to do that doesn’t really work with it. I’m mainly a C programmer and I’ve found unsigned integer wrapping to be useful in many situations. Especially when dealing with crypto algorithms.
Another lacking feature of Lua’s number type is its range. Lua 5.3 internally uses a signed 64 bit type which provides a decent range but it’s not always enough. Other scripting languages like Python doesn’t have a max size for numbers. Under the hood other languages use a BigNum library so you can use absurdly large numbers when you need to.
While neither BigNums a unsigned integer wrapping is something that’s needed often, they still have their place.
I’ve been working on a project that needs unsigned 64 bit numbers and instead of saying, “I just can do this with Lua”, I decided to make it work. I took a break from the project I was working on and I created Lua-nums! It’s a pure Lua number library that provides both a BigNum type and fixed width unsigned integers of various sizes. I should make it clear, this library is integer oriented and does not handle floating point in any way.
Obviously since it’s pure Lua performances is somewhat lacking. But I though it would be fun, and interesting to make this with Lua instead of writing a C module. It turned out pretty well and I’m especially happy with the BigNum type. Plus, it actually was a lot of fun.
For the BigNums I decided to use easy to understand algorithms and not the absolute fastest possible to really learn how to put something like this together. This doesn’t mean I’m using the most inefficient algorithms but performance is a bit… not really comparable to a C BigNum library. Oh, Python’s BigNums are implemented in C by the way.
Like other big name C BigNum libraries I’m using truncation (toward 0) based rounding. This might seem odd since Lua uses rounding toward negative infinity for its native numbers but I decided to be consistent with libtommath and GMP. Also, truncation is a lot easier.
I’ve heavily commented the BigNum source to explain how everything works. I geared the comments toward people who don’t have much math experience to make it more learning oriented. The unsigned integer files aren’t very well commented but really they just handle wrapping / reduction using mod. So there isn’t much to comment.
I made two unsigned integer types. One is backed by Lua’s native number type and the other by the BigNum type. Native numbers are faster but have a limited range. Unsigned 32 bit integers only. The BigNum backing is about 5x slower than the native one but it can handle any size. Like unsigned 64 bit integers.
Overall this was a very fun and interesting experience. Now I can continue on with what I set out to do in the first place. Hopefully.