Releasing Aljabar 1.0 and Some Reflections

Table of Contents

Back to my homepage

A little bit about aljabar…

For some context, this blog post is about aljabar, a linear algebra crate I wrote based heavily on const generics and other unstable Rust features. It is static and N-dimensional, meaning it supports linear algebra operators on vectors and matrices of any size.

When I published the first version of aljabar I guess about a year ago, I had no intention of it becoming the world's most popular and celebrated linear algebra library for rust game development. And it didn't. Frankly, I didn't think it would be at all usable for a long, long time. Not just because I anticipated the work on rust const generics would take a while - implementing a complicated compiler feature from scratch is challenging, implementing one on top of an already complicated compiler is a sisyphean nightmare - but I really had no intention of working on it beyond the initial demo. It was a fun exercise; a glimpse into the future that could and might someday be a reality.

However, the future came much faster than I had anticipated

The issues building aljabar were resolved must faster that I thought they were going to be, and I had just enough effort inside myself to keep occasionally working on the project and improving things. Before I knew it, the crate was in a decently clean, functional state. But there was still something wrong.

It probably wasn't a great idea to publish something to crates.io that I had written within 24 hours

There were a lot of glaring errors in the crate that were impossible to fix in a way that was compliant with semver. For reasons I just did not understand at the time I created a trait that only made the compiler work harder and was basically completely useless (it was called `SquareMatrix`). One other trait was just the `Real` trait but for trigonometric functions. It was an utter mess.

The only solution was to bump the version to "1.0". But bumping a version number is not just incrementing a counter, it's also an act of hubris. At the time of writing, only half of the most downloaded crates on crates.io have versions greater than 1.0. And the two other linear algebra crates that I think can be most easily compared to aljabar, cgmath and nalgebra, are at versions `0.17` and `0.21` respectively. When version numbers increase, people think that software is more mature. And not only is aljabar immature, it requires nightly to build. It's not something that screams "production ready", or, and this is what I'm concerned about is being conveyed, "better than the lexicographically lesser numbers".

But believe it or not I think some of y'all are not adhering to semver all that strictly

I use this only as an example because I interact with it regularly, but take the wonderful winit crate. By the way, if you don't use it for all your window and input handling needs already, I highly recommend doing so. But be sure to use the latest minor release, because at some point they changed their api and removed some thing that they used in the previous examples.

Now, I would like to be clear, the changes are just good in and of themselves. But I feel this is symptomatic of a problem that just needs to be addressed, which is why I have decided to set an example.

update: Turns out I'm fundamentally wrong about this point, and that is specifically because Cargo implements semver only for major versions greater than zero. According to Cargo, 0.15 is not a backwards compatible change with 0.14. To this point, I would like to say that you should still adhere to semver and not its Cargo pseudo-equivalent, but this convention still exists and should be respected.

Don't fear the 1.0

As our software evolves, our numbers will increase. That is just the way of the wind.

A lot of people writing Rust are still stuck in the idea that Rust is new and novel and exciting and cool. Well, yeah, it is exciting and cool. But It's exciting and cool in the same way that C was in 1985. And that is to say, you could be forgiven for not realizing it would change programming forever. But the car was already in gear, accelerating at a fast pace.

Rust has been around for nearly a decade, and people are going to keep using it for much longer. Why? Because it's fun! It's really fun to program in!

People forget that C is really fun to program in. Until it isn't. And that's why we have Rust!

So don't be afraid to finally start changing things, and removing your deprecated functions.

That being said…

Don't increment to 1.0 for no reason. I would like to say a lot of you just did it correctly in the first place. You designed your APIs well and they stood the test of time. All you had to do was add features and now you're at version `0.31298356.2`, and it's perfectly backwards compatible with `0.189927` (except for the bug fix). This is for the rest of you, the people like me, who make mistakes.

There has to be some rational for releasing a 1.0

But even then, releasing a 1.0 release has some sort of connection with "completeness", and for something to be complete it needs to have criteria for completion.

Personally, I would consider aljabar a success if I could use it for my own personal programming projects. These projects are typically interactive video graphics oriented, so for me that meant the following things needed to be true:

  • All of the data structures can be serialized and deserialized with serde.
  • All of the examples compile and work.
  • The `truncate` and `extend` functions compile and work.
  • Someone finally implements `Matrix::invert` and `determinant` for all `N`.

The first three issues were fundamentally issues with rustc and one by one were resolved. The final issue was solved by a kind soul on github named @Hovind, who implemented LU decomposition with partial pivoting. So now we have everything.

Comparison with cgmath 0.17

cgmath is a great crate. I love it. It's super simple, and it does the things that you need done. In fact, I have based one of my super-secret completion criterias that I didn't tell you about before on it; that is, aljabar can reach 1.0 when it is roughly fully compatible with cgmath. And that it is now. To be honest, aljabar is a little simpler than cgmath and doesn't provide an "Angles" trait, and could use a few more features here and there, but all of the things I personally seek out in cgmath are now present in aljabar.

If cgmath is so good, why even pursue another linear algebra library in the first place? Well, cgmath is showing its age in some forms, especially around SIMD, so hopefully this library can eventually implement more modern rust SIMD intrinsics. But it's a hard sell against cgmath, especially if you don't need the extra dimensions.

Comparison with nalgebra 0.21

aljabar is not intended to compete with nalgebra in any shape whatsoever, but interestingly is the only other crate that provides some of the features that nalgebra provides. For example, if you want to deserialize two 1000x1000 matrices from json files, multiply them together, invert that and then multiply THAT by a vector, then aljabar is literally the only other crate that can do that for you easily. I'm sure the machine learning capabilities deserve a grant, or something.

Especially after adding various iteration methods to matrices, aljabar certainly feels like a subset of nalgebra and a super set of cgmath. Maybe more like an extension of cgmath and a subset of nalgebra? I'm not sure, but it hits a happy middle ground that I'm finally excited to start using myself.

Okay, what's your conclusion based on all of this?

Beats me. I'm scheduling aljabar to be have 1.0 released on Friday, May 29th at noon. If you're reading this, then chances are that has already happened, and I encourage you to go give it a try.

Hopefully you don't notice any egregious api failures, because it's gonna take at least another year to address those.

Author: Matthew Plant

Email: map@maplant.com

Created: 2020-05-29 Fri 14:17

Validate