rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.94k stars 1.57k forks source link

arith-oflo: what is semantics of divide `int::MIN.wrapped_div(-1)` #964

Open pnkfelix opened 9 years ago

pnkfelix commented 9 years ago

I am working through implementing #560

I had thought, from the name "wrapping", that int::MIN.wrapped_div(-1) would be defined as follows:

    /// Returns `floor(a / b) mod 2^N`, where `N` is the width of `T` in bits.
    ///
    /// Note that for signed T:
    ///   `(floor(T::MIN / -1) mod 2^N) == (floor(T::MAX + 1) mod 2^N) == 1`
    pub fn overflowing_div<T>(a: T, b: T) -> T;

but then I saw this comment on the RFC thread:

https://github.com/rust-lang/rfcs/pull/560#issuecomment-72188471

which suggests: "there is no undefined behaviour or values left (if we agree to defining the result of INT_MIN/-1 as INT_MAX)."

My thinking is that if one wants the latter semantic, then maybe we should give it a name other than wrapping_div ... e.g. maybe have both:

    /// Returns `floor(a / b) mod 2^N`, where `N` is the width of `T` in bits.
    ///
    /// Note that for signed T:
    ///   `(floor(T::MIN / -1) mod 2^N) == (floor(T::MAX + 1) mod 2^N) == 1`
    pub fn wrapping_div<T>(a: T, b: T) -> T;

    /// Returns `floor(a / b)` clamped to the range `[-2^N, 2^N-1] mod 2^N`, where `N+1` is the width of `T` in bits.
    ///
    /// Note that for signed T:
    ///   `clamp(floor(T::MIN / -1)) == clamp(floor(T::MAX + 1)) == T::MAX`
    pub fn saturating_div<T>(a: T, b: T) -> T;

keywords: arithmetic overflow division divide wrapping

pnkfelix commented 9 years ago

cc @nikomatsakis

pnkfelix commented 9 years ago

(wait was my logic in the above totally bogus? yikes! namely, (floor(T::MAX + 1) mod 2^N) == 0, not 1!)

But in any case, there are other parts in the reasoning above that are really flawed; in particular, it should probably yield T::MIN, by analogy with how wrapping_mul behaves, right? (That is, the description "use floor(somethingsomething) mod 2^N" has no basis in what wrapping signed arithmetic does...)