Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit ergonomics #73

Merged
merged 40 commits into from
Feb 25, 2024
Merged

Unit ergonomics #73

merged 40 commits into from
Feb 25, 2024

Conversation

Tehforsch
Copy link
Owner

@Tehforsch Tehforsch commented Jan 22, 2024

Solves #56 #64 #52 #33

This completely revamps how units work and how their magnitudes are stored. Finally gets rid of all the in_... functions and replaces them by a single value_in function and opens the door for round_in etc. in the future.

The readme got restructured and in the process I switched to using cargo-rdme to generate the readme from lib.rs which makes the process a lot nicer and goes a long way to solving #58 .

For future me:
I went on a little bit of a detour while trying to solve the problem of how to represent the magnitude of a unit at compile time. Even if const_fn_float_arithmetic was stable, we arent allowed to use floats in const generics, so this approach is not an option right now.

For now, single units are represented with their magnitude decomposed into mantissa and exponent (which can be stored in a const generic) and then converted back to a float at runtime. This can be promoted to compile time once the corresponding features are stabilized.

I tried implementing multiplication and division using the mantissa/exponent representation, since this would make it possible to do this at compile time. However, even getting multiplication exactly right is very hard and division is virtually impossible. I don't know how exactly these algorithms are implemented on the CPU and at this point I also don't want to know anymore, but I am writing this down so that I don't attempt to do this anymore in the future.

Because of these limitations, at the moment an expression like meters * second is translated from two Units into a single RuntimeUnit in which the magnitude is stored at runtime. This means that, depending on compiler optimization, there could be some overhead in constructing a composite unit in an expression like (meters / second).new(50.0). I suspect that the compiler will optimize this away a lot of the times and also think that this is probably rarely performance-relevant. Nevertheless, I pointed the possibiliy out in the new readme and am waiting desperately for const supports for floats.

For the very far future, it could be nice to support arbitrary precision magnitudes using vector space magnitudes or some related concept. Currently, this is stopped by the strong limitations imposed by const fns. Even if one writes the code without requiring any allocations (by constructing a fixed size array of vector entries, for example) and avoids borrowing by painfully/carefully moving everywhere, one isnt even close to solving the problem, because even for loops are not allowed in const fns at the moment. So scratch that idea for the next couple of years.

@Tehforsch Tehforsch added documentation Improvements or additions to documentation enhancement New feature or request code-quality unit-safety Features relating to unit safety ergonomics Library usage ergonomics labels Jan 22, 2024
@Tehforsch Tehforsch force-pushed the unit-ergonomics branch 4 times, most recently from d6ea4bb to 07bfe2d Compare February 25, 2024 13:46
@Tehforsch Tehforsch merged commit d962a26 into main Feb 25, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code-quality documentation Improvements or additions to documentation enhancement New feature or request ergonomics Library usage ergonomics unit-safety Features relating to unit safety
Projects
None yet
1 participant