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

Add various arithmetic operations #39

Merged
merged 7 commits into from
Oct 24, 2023
Merged

Add various arithmetic operations #39

merged 7 commits into from
Oct 24, 2023

Conversation

danlehmann
Copy link
Owner

No description provided.

- Implement `wrapping_add`, `wrapping_sub`, `wrapping_mul`, `wrapping_div`, `wrapping_shl`, `wrapping_shr`
- In debug builds, `<<` (`Shl`, `ShlAssign`) and `>>` (`Shr`, `ShrAssign`) now bounds-check the shift amount using the same semantics as built-in shifts. For example, shifting a u5 by 5 or more bits will now panic as expected.
src/lib.rs Outdated
pub const fn saturating_mul(self, rhs: Self) -> Self {
let product = if BITS << 1 <= (core::mem::size_of::<$type>() << 3) {
// We have half the bits (e.g. u4 * u4) of the base type, so we can't overflow the base type
self.value * rhs.value
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not have to go through the “saturated” logic below, does it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, don’t you want to use wrapping_mul to avoid redundant checks in debug?

(Same up in shl/shr)?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the first question: Yes it does. An u4 is backed by an u8. u4 * u4 can't overflow u8 (hence we skip the first check), but it can still overflow an u4, so we need the second check.

For the second part: I guess - I didn't care too much about debug foot print, but changing to wrapping_mul shouldn't hurt

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For shl/shr: I decided to use << and >> as I'd expect that they perform better on cpus that don't by default do wrapping_shl. Slight hit in Debug builds on "normal" cpus, but optimal code everywhere in Release build

type Output = UInt<T, BITS>;

fn mul(self, rhs: Self) -> Self::Output {
let product = self.value * rhs.value;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has another overflow check in debug, right? We need it, but should have add a comment that there is another check that we can’t avoid?

// Integer division can only make the value smaller. And as the result is same type as
// Self, there's no need to range-check or mask
Self {
value: self.value / rhs.value,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the compiler know this though? Should we use an unchecked version to guarantee we avoid checks?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's unfortunately not a Trait for wrapping_div in regular Rust, so we can't express the generic in this way (num_traits has that, but that's an optional feature in this crate)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it matters too much though as I don't think the compiler checks anything here (what would it even test?)

@danlehmann danlehmann merged commit 7a8e97c into main Oct 24, 2023
6 checks passed
@danlehmann danlehmann deleted the arithmetic-ops1 branch October 24, 2023 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants