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 a method for computing the absolute difference between unsigned integers #62111

Closed
Centril opened this issue Jun 25, 2019 · 9 comments · Fixed by #88780
Closed

Add a method for computing the absolute difference between unsigned integers #62111

Centril opened this issue Jun 25, 2019 · 9 comments · Fixed by #88780
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Centril
Copy link
Contributor

Centril commented Jun 25, 2019

See discussion in #62103 (comment).

@Centril Centril added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Jun 25, 2019
@ExpHP
Copy link
Contributor

ExpHP commented Jun 25, 2019

I suggest not calling it abs_sub due to the confusion created by the (terribly misnamed) function on floats, whose tortured legacy continues to this day in num_traits::Signed.

@Centril
Copy link
Contributor Author

Centril commented Jun 26, 2019

@ExpHP abs_diff perhaps?

@leonardo-m
Copy link

abs_difference ?

@Centril
Copy link
Contributor Author

Centril commented Jun 27, 2019

What do you think about adding:

fn abs_difference<T: Sub<Output = T> + Ord>(x: T, y: T) -> T {
    if x < y {
        y - x
    } else {
        x - y
    }
}

instead of doing it on just the unsigned integer types?

@scalexm
Copy link
Member

scalexm commented Jul 1, 2019

distance is a good name, I think, as it is the mathematical term for abs(x-y).

I dislike @Centril’s above generalization, as what it does is unrelated with the name of the function in most cases (the first thing that comes to mind is that something called an « absolute difference » should be a non-negative real number).

@HeroicKatora
Copy link
Contributor

HeroicKatora commented Feb 5, 2020

The term distance seems too generic from the standpoint of a mathematical motivation, it is also used in the context of very different metric spaces than the normed space induced by the L1-norm. I think 'absolute difference' hits the nail on the head and with the given prior art of abbreviations that would make abs_diff my clear favorite. Similar to abs, checked_sub and other functions it doesn't seem necessary to add it in another way than as a method.

@Toniman575
Copy link

Until that happens, I've found the easiest way to do this is:
let x = max(y, z) - min(y, z);

@orlp
Copy link
Contributor

orlp commented Sep 9, 2021

If no one has any objections I can make a pull request implementing the following functions:

fn abs_diff(slf: u8,  other: u8)  -> u8;
fn abs_diff(slf: u16, other: u16) -> u16;
fn abs_diff(slf: u32, other: u32) -> u32;
fn abs_diff(slf: u64, other: u64) -> u64;
fn abs_diff(slf: u128, other: u128) -> u128;
fn abs_diff(slf: usize, other: usize) -> usize;
fn abs_diff(slf: i8,  other: i8)  -> u8;
fn abs_diff(slf: i16, other: i16) -> u16;
fn abs_diff(slf: i32, other: i32) -> u32;
fn abs_diff(slf: i64, other: i64) -> u64;
fn abs_diff(slf: i128, other: i128) -> u128;
fn abs_diff(slf: isize, other: isize) -> usize;

where for unsigned types the implementation would be

fn abs_diff(slf: U, other: U)  -> U {
    if slf < other {
        other - slf
    } else {
        slf - other
    }
}

and for signed types

fn abs_diff(slf: I, other: I)  -> U {
    if slf < other {
        (other as U).wrapping_sub(slf as U)
    } else {
        (slf as U).wrapping_sub(other as U)
    }
}

Especially the latter is a useful contribution as it is somewhat non-trivial and tricky to write correctly as a user, if you are not intimately familiar with two's complement.

Manishearth added a commit to Manishearth/rust that referenced this issue Oct 5, 2021
Manishearth added a commit to Manishearth/rust that referenced this issue Oct 5, 2021
Manishearth added a commit to Manishearth/rust that referenced this issue Oct 5, 2021
Manishearth added a commit to Manishearth/rust that referenced this issue Oct 5, 2021
@bors bors closed this as completed in 234fa90 Oct 5, 2021
@sffc
Copy link

sffc commented May 21, 2022

Just sharing some experience from the wild: I have code of the form

// a and b are i16
if a > b {
    let c = a.abs_diff(b) as usize;
    // do something with c
}

where I check if a > b before I call abs_diff, because I need a different code path for that case versus the a <= b case. However, that check is repeated within the abs_diff impl, so I was wondering whether I should write out the wrapping_sub manually. But, it appears that when the compiler decides to inline abs_diff, it is smart enough to collapse the if statements into one. So I think using vanilla abs_diff is fine for my case. Thanks for adding it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants