Skip to content

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

New issue

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

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

Already on GitHub? # to your account

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).

@197g
Copy link
Contributor

197g 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!

# for free to join this conversation on GitHub. Already have an account? # 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