Merge branch 'master' into reverse-bits

This commit is contained in:
Josh Stone
2021-06-15 17:30:17 -07:00
committed by GitHub
7 changed files with 235 additions and 263 deletions
-6
View File
@@ -16,12 +16,6 @@ Add this to your `Cargo.toml`:
num-traits = "0.2"
```
and this to your crate root:
```rust
extern crate num_traits;
```
## Features
This crate can be used without the standard library (`#![no_std]`) by disabling
+1
View File
@@ -17,6 +17,7 @@ fn main() {
);
ac.emit_expression_cfg("1u32.reverse_bits()", "has_reverse_bits");
ac.emit_expression_cfg("1u32.trailing_ones()", "has_leading_trailing_ones");
autocfg::rerun_path("build.rs");
}
+28 -2
View File
@@ -8,12 +8,38 @@ use core::{u16, u32, u64, u8, usize};
/// Numbers which have upper and lower bounds
pub trait Bounded {
// FIXME (#5527): These should be associated constants
/// returns the smallest finite number this type can represent
/// Returns the smallest finite number this type can represent
fn min_value() -> Self;
/// returns the largest finite number this type can represent
/// Returns the largest finite number this type can represent
fn max_value() -> Self;
}
/// Numbers which have lower bounds
pub trait LowerBounded {
/// Returns the smallest finite number this type can represent
fn min_value() -> Self;
}
// FIXME: With a major version bump, this should be a supertrait instead
impl<T: Bounded> LowerBounded for T {
fn min_value() -> T {
Bounded::min_value()
}
}
/// Numbers which have upper bounds
pub trait UpperBounded {
/// Returns the largest finite number this type can represent
fn max_value() -> Self;
}
// FIXME: With a major version bump, this should be a supertrait instead
impl<T: Bounded> UpperBounded for T {
fn max_value() -> T {
Bounded::max_value()
}
}
macro_rules! bounded_impl {
($t:ty, $min:expr, $max:expr) => {
impl Bounded for $t {
+105 -249
View File
@@ -818,6 +818,23 @@ impl FloatCore for f32 {
Self::to_degrees(self) -> Self;
Self::to_radians(self) -> Self;
}
#[cfg(all(not(feature = "std"), feature = "libm"))]
forward! {
libm::floorf as floor(self) -> Self;
libm::ceilf as ceil(self) -> Self;
libm::roundf as round(self) -> Self;
libm::truncf as trunc(self) -> Self;
libm::fabsf as abs(self) -> Self;
libm::fminf as min(self, other: Self) -> Self;
libm::fmaxf as max(self, other: Self) -> Self;
}
#[cfg(all(not(feature = "std"), feature = "libm"))]
#[inline]
fn fract(self) -> Self {
self - libm::truncf(self)
}
}
impl FloatCore for f64 {
@@ -893,6 +910,23 @@ impl FloatCore for f64 {
Self::to_degrees(self) -> Self;
Self::to_radians(self) -> Self;
}
#[cfg(all(not(feature = "std"), feature = "libm"))]
forward! {
libm::floor as floor(self) -> Self;
libm::ceil as ceil(self) -> Self;
libm::round as round(self) -> Self;
libm::trunc as trunc(self) -> Self;
libm::fabs as abs(self) -> Self;
libm::fmin as min(self, other: Self) -> Self;
libm::fmax as max(self, other: Self) -> Self;
}
#[cfg(all(not(feature = "std"), feature = "libm"))]
#[inline]
fn fract(self) -> Self {
self - libm::trunc(self)
}
}
// FIXME: these doctests aren't actually helpful, because they're using and
@@ -1908,7 +1942,7 @@ macro_rules! float_impl_libm {
#[inline]
fn fract(self) -> Self {
self - FloatCore::trunc(self)
self - Float::trunc(self)
}
#[inline]
@@ -1929,8 +1963,6 @@ macro_rules! float_impl_libm {
FloatCore::powi(self, n: i32) -> Self;
FloatCore::to_degrees(self) -> Self;
FloatCore::to_radians(self) -> Self;
FloatCore::max(self, other: Self) -> Self;
FloatCore::min(self, other: Self) -> Self;
}
};
}
@@ -1981,129 +2013,41 @@ impl Float for f32 {
fn abs_sub(self, other: Self) -> Self {
libm::fdimf(self, other)
}
#[inline]
fn floor(self) -> Self {
libm::floorf(self)
}
#[inline]
fn ceil(self) -> Self {
libm::ceilf(self)
}
#[inline]
fn round(self) -> Self {
libm::roundf(self)
}
#[inline]
fn trunc(self) -> Self {
libm::truncf(self)
}
#[inline]
fn abs(self) -> Self {
libm::fabsf(self)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm::fmaf(self, a, b)
}
#[inline]
fn powf(self, n: Self) -> Self {
libm::powf(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrtf(self)
}
#[inline]
fn exp(self) -> Self {
libm::expf(self)
}
#[inline]
fn exp2(self) -> Self {
libm::exp2f(self)
}
#[inline]
fn ln(self) -> Self {
libm::logf(self)
}
#[inline]
fn log2(self) -> Self {
libm::log2f(self)
}
#[inline]
fn log10(self) -> Self {
libm::log10f(self)
}
#[inline]
fn cbrt(self) -> Self {
libm::cbrtf(self)
}
#[inline]
fn hypot(self, other: Self) -> Self {
libm::hypotf(self, other)
}
#[inline]
fn sin(self) -> Self {
libm::sinf(self)
}
#[inline]
fn cos(self) -> Self {
libm::cosf(self)
}
#[inline]
fn tan(self) -> Self {
libm::tanf(self)
}
#[inline]
fn asin(self) -> Self {
libm::asinf(self)
}
#[inline]
fn acos(self) -> Self {
libm::acosf(self)
}
#[inline]
fn atan(self) -> Self {
libm::atanf(self)
}
#[inline]
fn atan2(self, other: Self) -> Self {
libm::atan2f(self, other)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
libm::sincosf(self)
}
#[inline]
fn exp_m1(self) -> Self {
libm::expm1f(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm::log1pf(self)
}
#[inline]
fn sinh(self) -> Self {
libm::sinhf(self)
}
#[inline]
fn cosh(self) -> Self {
libm::coshf(self)
}
#[inline]
fn tanh(self) -> Self {
libm::tanhf(self)
}
#[inline]
fn asinh(self) -> Self {
libm::asinhf(self)
}
#[inline]
fn acosh(self) -> Self {
libm::acoshf(self)
}
#[inline]
fn atanh(self) -> Self {
libm::atanhf(self)
forward! {
libm::floorf as floor(self) -> Self;
libm::ceilf as ceil(self) -> Self;
libm::roundf as round(self) -> Self;
libm::truncf as trunc(self) -> Self;
libm::fabsf as abs(self) -> Self;
libm::fmaf as mul_add(self, a: Self, b: Self) -> Self;
libm::powf as powf(self, n: Self) -> Self;
libm::sqrtf as sqrt(self) -> Self;
libm::expf as exp(self) -> Self;
libm::exp2f as exp2(self) -> Self;
libm::logf as ln(self) -> Self;
libm::log2f as log2(self) -> Self;
libm::log10f as log10(self) -> Self;
libm::cbrtf as cbrt(self) -> Self;
libm::hypotf as hypot(self, other: Self) -> Self;
libm::sinf as sin(self) -> Self;
libm::cosf as cos(self) -> Self;
libm::tanf as tan(self) -> Self;
libm::asinf as asin(self) -> Self;
libm::acosf as acos(self) -> Self;
libm::atanf as atan(self) -> Self;
libm::atan2f as atan2(self, other: Self) -> Self;
libm::sincosf as sin_cos(self) -> (Self, Self);
libm::expm1f as exp_m1(self) -> Self;
libm::log1pf as ln_1p(self) -> Self;
libm::sinhf as sinh(self) -> Self;
libm::coshf as cosh(self) -> Self;
libm::tanhf as tanh(self) -> Self;
libm::asinhf as asinh(self) -> Self;
libm::acoshf as acosh(self) -> Self;
libm::atanhf as atanh(self) -> Self;
libm::fmaxf as max(self, other: Self) -> Self;
libm::fminf as min(self, other: Self) -> Self;
}
}
@@ -2116,129 +2060,41 @@ impl Float for f64 {
fn abs_sub(self, other: Self) -> Self {
libm::fdim(self, other)
}
#[inline]
fn floor(self) -> Self {
libm::floor(self)
}
#[inline]
fn ceil(self) -> Self {
libm::ceil(self)
}
#[inline]
fn round(self) -> Self {
libm::round(self)
}
#[inline]
fn trunc(self) -> Self {
libm::trunc(self)
}
#[inline]
fn abs(self) -> Self {
libm::fabs(self)
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
libm::fma(self, a, b)
}
#[inline]
fn powf(self, n: Self) -> Self {
libm::pow(self, n)
}
#[inline]
fn sqrt(self) -> Self {
libm::sqrt(self)
}
#[inline]
fn exp(self) -> Self {
libm::exp(self)
}
#[inline]
fn exp2(self) -> Self {
libm::exp2(self)
}
#[inline]
fn ln(self) -> Self {
libm::log(self)
}
#[inline]
fn log2(self) -> Self {
libm::log2(self)
}
#[inline]
fn log10(self) -> Self {
libm::log10(self)
}
#[inline]
fn cbrt(self) -> Self {
libm::cbrt(self)
}
#[inline]
fn hypot(self, other: Self) -> Self {
libm::hypot(self, other)
}
#[inline]
fn sin(self) -> Self {
libm::sin(self)
}
#[inline]
fn cos(self) -> Self {
libm::cos(self)
}
#[inline]
fn tan(self) -> Self {
libm::tan(self)
}
#[inline]
fn asin(self) -> Self {
libm::asin(self)
}
#[inline]
fn acos(self) -> Self {
libm::acos(self)
}
#[inline]
fn atan(self) -> Self {
libm::atan(self)
}
#[inline]
fn atan2(self, other: Self) -> Self {
libm::atan2(self, other)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
libm::sincos(self)
}
#[inline]
fn exp_m1(self) -> Self {
libm::expm1(self)
}
#[inline]
fn ln_1p(self) -> Self {
libm::log1p(self)
}
#[inline]
fn sinh(self) -> Self {
libm::sinh(self)
}
#[inline]
fn cosh(self) -> Self {
libm::cosh(self)
}
#[inline]
fn tanh(self) -> Self {
libm::tanh(self)
}
#[inline]
fn asinh(self) -> Self {
libm::asinh(self)
}
#[inline]
fn acosh(self) -> Self {
libm::acosh(self)
}
#[inline]
fn atanh(self) -> Self {
libm::atanh(self)
forward! {
libm::floor as floor(self) -> Self;
libm::ceil as ceil(self) -> Self;
libm::round as round(self) -> Self;
libm::trunc as trunc(self) -> Self;
libm::fabs as abs(self) -> Self;
libm::fma as mul_add(self, a: Self, b: Self) -> Self;
libm::pow as powf(self, n: Self) -> Self;
libm::sqrt as sqrt(self) -> Self;
libm::exp as exp(self) -> Self;
libm::exp2 as exp2(self) -> Self;
libm::log as ln(self) -> Self;
libm::log2 as log2(self) -> Self;
libm::log10 as log10(self) -> Self;
libm::cbrt as cbrt(self) -> Self;
libm::hypot as hypot(self, other: Self) -> Self;
libm::sin as sin(self) -> Self;
libm::cos as cos(self) -> Self;
libm::tan as tan(self) -> Self;
libm::asin as asin(self) -> Self;
libm::acos as acos(self) -> Self;
libm::atan as atan(self) -> Self;
libm::atan2 as atan2(self, other: Self) -> Self;
libm::sincos as sin_cos(self) -> (Self, Self);
libm::expm1 as exp_m1(self) -> Self;
libm::log1p as ln_1p(self) -> Self;
libm::sinh as sinh(self) -> Self;
libm::cosh as cosh(self) -> Self;
libm::tanh as tanh(self) -> Self;
libm::asinh as asinh(self) -> Self;
libm::acosh as acosh(self) -> Self;
libm::atanh as atanh(self) -> Self;
libm::fmax as max(self, other: Self) -> Self;
libm::fmin as min(self, other: Self) -> Self;
}
}
+44
View File
@@ -78,6 +78,22 @@ pub trait PrimInt:
/// ```
fn count_zeros(self) -> u32;
/// Returns the number of leading ones in the binary representation
/// of `self`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0xF00Du16;
///
/// assert_eq!(n.leading_ones(), 4);
/// ```
fn leading_ones(self) -> u32 {
(!self).leading_zeros()
}
/// Returns the number of leading zeros in the binary representation
/// of `self`.
///
@@ -92,6 +108,22 @@ pub trait PrimInt:
/// ```
fn leading_zeros(self) -> u32;
/// Returns the number of trailing ones in the binary representation
/// of `self`.
///
/// # Examples
///
/// ```
/// use num_traits::PrimInt;
///
/// let n = 0xBEEFu16;
///
/// assert_eq!(n.trailing_ones(), 4);
/// ```
fn trailing_ones(self) -> u32 {
(!self).trailing_zeros()
}
/// Returns the number of trailing zeros in the binary representation
/// of `self`.
///
@@ -372,11 +404,23 @@ macro_rules! prim_int_impl {
<$T>::count_zeros(self)
}
#[cfg(has_leading_leading_ones)]
#[inline]
fn leading_ones(self) -> u32 {
<$T>::leading_ones(self)
}
#[inline]
fn leading_zeros(self) -> u32 {
<$T>::leading_zeros(self)
}
#[cfg(has_leading_trailing_ones)]
#[inline]
fn trailing_ones(self) -> u32 {
<$T>::trailing_ones(self)
}
#[inline]
fn trailing_zeros(self) -> u32 {
<$T>::trailing_zeros(self)
+49 -5
View File
@@ -210,6 +210,14 @@ impl fmt::Display for ParseFloatError {
}
}
fn str_to_ascii_lower_eq_str(a: &str, b: &str) -> bool {
a.len() == b.len()
&& a.bytes().zip(b.bytes()).all(|(a, b)| {
let a_to_ascii_lower = a | (((b'A' <= a && a <= b'Z') as u8) << 5);
a_to_ascii_lower == b
})
}
// FIXME: The standard library from_str_radix on floats was deprecated, so we're stuck
// with this implementation ourselves until we want to make a breaking change.
// (would have to drop it from `Num` though)
@@ -224,12 +232,26 @@ macro_rules! float_trait_impl {
use self::FloatErrorKind::*;
use self::ParseFloatError as PFE;
// Special case radix 10 to use more accurate standard library implementation
if radix == 10 {
return src.parse().map_err(|_| PFE {
kind: if src.is_empty() { Empty } else { Invalid },
});
}
// Special values
match src {
"inf" => return Ok(core::$t::INFINITY),
"-inf" => return Ok(core::$t::NEG_INFINITY),
"NaN" => return Ok(core::$t::NAN),
_ => {},
if str_to_ascii_lower_eq_str(src, "inf")
|| str_to_ascii_lower_eq_str(src, "infinity")
{
return Ok(core::$t::INFINITY);
} else if str_to_ascii_lower_eq_str(src, "-inf")
|| str_to_ascii_lower_eq_str(src, "-infinity")
{
return Ok(core::$t::NEG_INFINITY);
} else if str_to_ascii_lower_eq_str(src, "nan") {
return Ok(core::$t::NAN);
} else if str_to_ascii_lower_eq_str(src, "-nan") {
return Ok(-core::$t::NAN);
}
fn slice_shift_char(src: &str) -> Option<(char, &str)> {
@@ -508,6 +530,28 @@ fn from_str_radix_multi_byte_fail() {
assert!(f32::from_str_radix("0.2E™1", 10).is_err());
}
#[test]
fn from_str_radix_ignore_case() {
assert_eq!(
f32::from_str_radix("InF", 16).unwrap(),
::core::f32::INFINITY
);
assert_eq!(
f32::from_str_radix("InfinitY", 16).unwrap(),
::core::f32::INFINITY
);
assert_eq!(
f32::from_str_radix("-InF", 8).unwrap(),
::core::f32::NEG_INFINITY
);
assert_eq!(
f32::from_str_radix("-InfinitY", 8).unwrap(),
::core::f32::NEG_INFINITY
);
assert!(f32::from_str_radix("nAn", 4).unwrap().is_nan());
assert!(f32::from_str_radix("-nAn", 4).unwrap().is_nan());
}
#[test]
fn wrapping_is_num() {
fn require_num<T: Num>(_: &T) {}
+8 -1
View File
@@ -23,7 +23,14 @@ macro_rules! forward {
fn $method( $( $arg : $ty ),* ) -> $ret {
<Self as $base>::$method( $( $arg ),* )
}
)*}
)*};
($( $imp:path as $method:ident ( self $( , $arg:ident : $ty:ty )* ) -> $ret:ty ; )*)
=> {$(
#[inline]
fn $method(self $( , $arg : $ty )* ) -> $ret {
$imp(self $( , $arg )* )
}
)*};
}
macro_rules! constant {