Auto merge of #49389 - fanzier:euclidean-division, r=KodrAus

Implement RFC #2169 (Euclidean modulo).

Tracking issue: #49048
This commit is contained in:
bors
2018-04-13 07:34:37 +00:00
3 changed files with 541 additions and 0 deletions

View File

@@ -329,6 +329,57 @@ impl f32 {
unsafe { intrinsics::fmaf32(self, a, b) }
}
/// Calculates Euclidean division, the matching method for `mod_euc`.
///
/// This computes the integer `n` such that
/// `self = n * rhs + self.mod_euc(rhs)`.
/// In other words, the result is `self / rhs` rounded to the integer `n`
/// such that `self >= n * rhs`.
///
/// ```
/// #![feature(euclidean_division)]
/// let a: f32 = 7.0;
/// let b = 4.0;
/// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
/// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
/// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
/// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
pub fn div_euc(self, rhs: f32) -> f32 {
let q = (self / rhs).trunc();
if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
}
q
}
/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
///
/// ```
/// #![feature(euclidean_division)]
/// let a: f32 = 7.0;
/// let b = 4.0;
/// assert_eq!(a.mod_euc(b), 3.0);
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
pub fn mod_euc(self, rhs: f32) -> f32 {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```

View File

@@ -315,6 +315,56 @@ impl f64 {
unsafe { intrinsics::fmaf64(self, a, b) }
}
/// Calculates Euclidean division, the matching method for `mod_euc`.
///
/// This computes the integer `n` such that
/// `self = n * rhs + self.mod_euc(rhs)`.
/// In other words, the result is `self / rhs` rounded to the integer `n`
/// such that `self >= n * rhs`.
///
/// ```
/// #![feature(euclidean_division)]
/// let a: f64 = 7.0;
/// let b = 4.0;
/// assert_eq!(a.div_euc(b), 1.0); // 7.0 > 4.0 * 1.0
/// assert_eq!((-a).div_euc(b), -2.0); // -7.0 >= 4.0 * -2.0
/// assert_eq!(a.div_euc(-b), -1.0); // 7.0 >= -4.0 * -1.0
/// assert_eq!((-a).div_euc(-b), 2.0); // -7.0 >= -4.0 * 2.0
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
pub fn div_euc(self, rhs: f64) -> f64 {
let q = (self / rhs).trunc();
if self % rhs < 0.0 {
return if rhs > 0.0 { q - 1.0 } else { q + 1.0 }
}
q
}
/// Calculates the Euclidean modulo (self mod rhs), which is never negative.
///
/// In particular, the result `n` satisfies `0 <= n < rhs.abs()`.
///
/// ```
/// #![feature(euclidean_division)]
/// let a: f64 = 7.0;
/// let b = 4.0;
/// assert_eq!(a.mod_euc(b), 3.0);
/// assert_eq!((-a).mod_euc(b), 1.0);
/// assert_eq!(a.mod_euc(-b), 3.0);
/// assert_eq!((-a).mod_euc(-b), 1.0);
/// ```
#[inline]
#[unstable(feature = "euclidean_division", issue = "49048")]
pub fn mod_euc(self, rhs: f64) -> f64 {
let r = self % rhs;
if r < 0.0 {
r + rhs.abs()
} else {
r
}
}
/// Takes the reciprocal (inverse) of a number, `1/x`.
///
/// ```