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 saturating_cast between integers #23596

Closed
mahkoh opened this issue Mar 21, 2015 · 8 comments
Closed

Add a saturating_cast between integers #23596

mahkoh opened this issue Mar 21, 2015 · 8 comments
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@mahkoh
Copy link
Contributor

mahkoh commented Mar 21, 2015

Similar to saturating_add but for casts. Untested implementation below.

use std;

pub trait IntExt<T> {
    fn saturating_cast(self) -> T;
}

// truncations that always preserve the value
macro_rules! trnc_up {
    ($src:ty as $($dst:ty),+) => {
        $(impl IntExt<$dst> for $src {
            fn saturating_cast(self) -> $dst {
                self as $dst
            }
        })+
    }
}

trnc_up!(u8 as u8, u16, i16, u32, i32, u64, i64, usize, isize);
trnc_up!(i8 as i8, i16, i32, i64, isize);
trnc_up!(u16 as u16, u32, i32, u64, i64, usize, isize);
trnc_up!(i16 as i16, i32, i64, isize);
trnc_up!(u32 as u32, u64, i64, usize);
trnc_up!(i32 as i32, i64, isize);
trnc_up!(u64 as u64);
trnc_up!(i64 as i64);
trnc_up!(usize as u64, usize);
trnc_up!(isize as i64, isize);
#[cfg(target_word_size = "64")]
trnc_up!(u64 as usize);
#[cfg(target_word_size = "64")]
trnc_up!(i64 as isize);
#[cfg(target_word_size = "32")]
trnc_up!(usize as u32);
#[cfg(target_word_size = "32")]
trnc_up!(isize as i32);

// truncations of signed tyes to unsigned types of equal or larger width
macro_rules! trnc_s2u_up {
    ($src:ty as $($dst:ty),+) => {
        $(impl IntExt<$dst> for $src {
            fn saturating_cast(self) -> $dst {
                if self >= 0 {
                    self as $dst
                } else {
                    0
                }
            }
        })+
    }
}

trnc_s2u_up!(i8 as u8, u16, u32, u64, usize);
trnc_s2u_up!(i16 as u16, u32, u64, usize);
trnc_s2u_up!(i32 as u32, u64, usize);
trnc_s2u_up!(i64 as u64);
trnc_s2u_up!(isize as usize);
#[cfg(target_word_size = "64")]
trnc_s2u_up!(i64 as usize);
#[cfg(target_word_size = "32")]
trnc_s2u_up!(isize as u32);

// truncation of signed types to types of smaller width
macro_rules! trnc_s_down {
    ($src:ty as $($dst:ident),+) => {
        $(impl IntExt<$dst> for $src {
            fn saturating_cast(self) -> $dst {
                if self > std::$dst::MAX as $src  {
                    std::$dst::MAX
                } else if self < std::$dst::MIN as $src {
                    std::$dst::MIN
                } else {
                    self as $dst
                }
            }
        })+
    }
}

trnc_s_down!(i16 as u8, i8);
trnc_s_down!(i32 as u8, i8, u16, i16);
trnc_s_down!(i64 as u8, i8, u16, i16, u32, i32);
trnc_s_down!(isize as u8, i8, u16, i16);
#[cfg(target_word_size = "64")]
trnc_s_down!(isize as u32, i32);
#[cfg(target_word_size = "32")]
trnc_s_down!(i64 as usize, isize);

// truncation of unsigned types to types of equal or smaller width
macro_rules! trnc_u_down {
    ($src:ty as $($dst:ident),+) => {
        $(impl IntExt<$dst> for $src {
            fn saturating_cast(self) -> $dst {
                if self > std::$dst::MAX as $src  {
                    std::$dst::MAX
                } else {
                    self as $dst
                }
            }
        })+
    }
}

trnc_u_down!(u16 as i8, u8, i16);
trnc_u_down!(u32 as i8, u8, i16, u16, i32);
trnc_u_down!(u64 as i8, u8, i16, u16, i32, u32, i64);
trnc_u_down!(usize as i8, u8, i16, u16, i32);
#[cfg(target_word_size = "64")]
trnc_u_down!(usize as u32, i64);
#[cfg(target_word_size = "32")]
trnc_u_down!(u64 as isize, usize);
@steveklabnik
Copy link
Member

These kinds of additions to the language will also need to go through an RFC, and feature request stuff goes in the RFC repo these days.

@nikomatsakis
Copy link
Contributor

Actually, it's unclear that this needs to go through an RFC; it could be considered part of the work on the overflow RFC. But I think whether or not it is useful will depend on the final outcome re: the handling of casts.

cc @pnkfelix

@nikomatsakis nikomatsakis reopened this Mar 23, 2015
@nikomatsakis
Copy link
Contributor

cc #22020

@nikomatsakis
Copy link
Contributor

Also, @mahkoh, is there some particular reason you included a sample implementation with a license that is not compatible with Rust? That is, was that unintentional, or did you want to be sure we would not use this sample code? If the latter, that's fine, but then it's not clear why you are putting it in the ticket.

@mahkoh
Copy link
Contributor Author

mahkoh commented Mar 23, 2015

You can't use code posted without a license either because without a license it's proprietary. In this case I just copied the whole file including the header.

@pnkfelix
Copy link
Member

@mahkoh so shall I take your comment as implicitly saying that we do not have your permission to use this code? In that case I might as well delete it, lest someone accidentally try to use it as the basis for an implementation.

@mahkoh
Copy link
Contributor Author

mahkoh commented Mar 24, 2015

I obviously posted it because I want you to use it and the license header was there by accident.

In the previous post I merely pointed out that @nikomatsakis's question was based on the wrong assumption that all code posted here without a license can automatically be used. No code that isn't explicitly posted with the correct licensing can be used automatically.

@pnkfelix
Copy link
Member

@mahkoh Thank you for clarifying your intent.

@steveklabnik steveklabnik added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Mar 24, 2015
@mahkoh mahkoh closed this as completed Apr 11, 2015
@rust-lang rust-lang locked and limited conversation to collaborators Apr 11, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

4 participants