Compare commits
No commits in common. "master" and "num-traits-0.2.5" have entirely different histories.
master
...
num-traits
33
.travis.yml
33
.travis.yml
|
@ -1,46 +1,15 @@
|
||||||
language: rust
|
language: rust
|
||||||
sudo: false
|
|
||||||
rust:
|
rust:
|
||||||
- 1.8.0
|
- 1.8.0
|
||||||
- 1.15.0
|
- 1.15.0
|
||||||
- 1.20.0
|
- 1.20.0
|
||||||
- 1.26.0 # has_i128
|
|
||||||
- 1.31.0 # 2018!
|
|
||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
|
sudo: false
|
||||||
script:
|
script:
|
||||||
- cargo build --verbose
|
- cargo build --verbose
|
||||||
- ./ci/test_full.sh
|
- ./ci/test_full.sh
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# i586 presents floating point challenges for lack of SSE/SSE2
|
|
||||||
- name: "i586"
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=i586-unknown-linux-gnu
|
|
||||||
addons:
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- gcc-multilib
|
|
||||||
before_script:
|
|
||||||
- rustup target add $TARGET
|
|
||||||
script:
|
|
||||||
- cargo test --verbose --target $TARGET --all-features
|
|
||||||
# try a target that doesn't have std at all
|
|
||||||
- name: "no_std"
|
|
||||||
rust: stable
|
|
||||||
env: TARGET=thumbv6m-none-eabi
|
|
||||||
before_script:
|
|
||||||
- rustup target add $TARGET
|
|
||||||
script:
|
|
||||||
- cargo build --verbose --target $TARGET --no-default-features --features i128
|
|
||||||
- cargo build --verbose --target $TARGET --no-default-features --features libm
|
|
||||||
- name: "rustfmt"
|
|
||||||
rust: 1.31.0
|
|
||||||
before_script:
|
|
||||||
- rustup component add rustfmt
|
|
||||||
script:
|
|
||||||
- cargo fmt --all -- --check
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email:
|
||||||
on_success: never
|
on_success: never
|
||||||
|
|
|
@ -8,21 +8,16 @@ categories = ["algorithms", "science", "no-std"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
repository = "https://github.com/rust-num/num-traits"
|
repository = "https://github.com/rust-num/num-traits"
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.8"
|
version = "0.2.5"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
exclude = ["/ci/*", "/.travis.yml", "/bors.toml"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["std"]
|
features = ["std"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libm = { version = "0.1.4", optional = true }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
std = []
|
std = []
|
||||||
i128 = []
|
i128 = []
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
autocfg = "0.1.3"
|
|
||||||
|
|
|
@ -31,14 +31,11 @@ the default `std` feature. Use this in `Cargo.toml`:
|
||||||
[dependencies.num-traits]
|
[dependencies.num-traits]
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
default-features = false
|
default-features = false
|
||||||
# features = ["libm"] # <--- Uncomment if you wish to use `Float` and `Real` without `std`
|
|
||||||
```
|
```
|
||||||
|
|
||||||
The `Float` and `Real` traits are only available when either `std` or `libm` is enabled.
|
The `Float` and `Real` traits are only available when `std` is enabled. The
|
||||||
The `libm` feature is only available with Rust 1.31 and later ([see PR #99](https://github.com/rust-num/num-traits/pull/99)).
|
`FloatCore` trait is always available. `MulAdd` and `MulAddAssign` for `f32`
|
||||||
|
and `f64` also require `std`, as do implementations of signed and floating-
|
||||||
The `FloatCore` trait is always available. `MulAdd` and `MulAddAssign` for `f32`
|
|
||||||
and `f64` also require `std` or `libm`, as do implementations of signed and floating-
|
|
||||||
point exponents in `Pow`.
|
point exponents in `Pow`.
|
||||||
|
|
||||||
Implementations for `i128` and `u128` are only available with Rust 1.26 and
|
Implementations for `i128` and `u128` are only available with Rust 1.26 and
|
||||||
|
|
50
RELEASES.md
50
RELEASES.md
|
@ -1,38 +1,4 @@
|
||||||
# Release 0.2.8 (2019-05-21)
|
# Release 0.2.5
|
||||||
|
|
||||||
- [Fixed feature detection on `no_std` targets][116].
|
|
||||||
|
|
||||||
**Contributors**: @cuviper
|
|
||||||
|
|
||||||
[116]: https://github.com/rust-num/num-traits/pull/116
|
|
||||||
|
|
||||||
# Release 0.2.7 (2019-05-20)
|
|
||||||
|
|
||||||
- [Documented when `CheckedShl` and `CheckedShr` return `None`][90].
|
|
||||||
- [The new `Zero::set_zero` and `One::set_one`][104] will set values to their
|
|
||||||
identities in place, possibly optimized better than direct assignment.
|
|
||||||
- [Documented general features and intentions of `PrimInt`][108].
|
|
||||||
|
|
||||||
**Contributors**: @cuviper, @dvdhrm, @ignatenkobrain, @lcnr, @samueltardieu
|
|
||||||
|
|
||||||
[90]: https://github.com/rust-num/num-traits/pull/90
|
|
||||||
[104]: https://github.com/rust-num/num-traits/pull/104
|
|
||||||
[108]: https://github.com/rust-num/num-traits/pull/108
|
|
||||||
|
|
||||||
# Release 0.2.6 (2018-09-13)
|
|
||||||
|
|
||||||
- [Documented that `pow(0, 0)` returns `1`][79]. Mathematically, this is not
|
|
||||||
strictly defined, but the current behavior is a pragmatic choice that has
|
|
||||||
precedent in Rust `core` for the primitives and in many other languages.
|
|
||||||
- [The new `WrappingShl` and `WrappingShr` traits][81] will wrap the shift count
|
|
||||||
if it exceeds the bit size of the type.
|
|
||||||
|
|
||||||
**Contributors**: @cuviper, @edmccard, @meltinglava
|
|
||||||
|
|
||||||
[79]: https://github.com/rust-num/num-traits/pull/79
|
|
||||||
[81]: https://github.com/rust-num/num-traits/pull/81
|
|
||||||
|
|
||||||
# Release 0.2.5 (2018-06-20)
|
|
||||||
|
|
||||||
- [Documentation for `mul_add` now clarifies that it's not always faster.][70]
|
- [Documentation for `mul_add` now clarifies that it's not always faster.][70]
|
||||||
- [The default methods in `FromPrimitive` and `ToPrimitive` are more robust.][73]
|
- [The default methods in `FromPrimitive` and `ToPrimitive` are more robust.][73]
|
||||||
|
@ -42,7 +8,7 @@
|
||||||
[70]: https://github.com/rust-num/num-traits/pull/70
|
[70]: https://github.com/rust-num/num-traits/pull/70
|
||||||
[73]: https://github.com/rust-num/num-traits/pull/73
|
[73]: https://github.com/rust-num/num-traits/pull/73
|
||||||
|
|
||||||
# Release 0.2.4 (2018-05-11)
|
# Release 0.2.4
|
||||||
|
|
||||||
- [Support for 128-bit integers is now automatically detected and enabled.][69]
|
- [Support for 128-bit integers is now automatically detected and enabled.][69]
|
||||||
Setting the `i128` crate feature now causes the build script to panic if such
|
Setting the `i128` crate feature now causes the build script to panic if such
|
||||||
|
@ -52,7 +18,7 @@
|
||||||
|
|
||||||
[69]: https://github.com/rust-num/num-traits/pull/69
|
[69]: https://github.com/rust-num/num-traits/pull/69
|
||||||
|
|
||||||
# Release 0.2.3 (2018-05-10)
|
# Release 0.2.3
|
||||||
|
|
||||||
- [The new `CheckedNeg` and `CheckedRem` traits][63] perform checked `Neg` and
|
- [The new `CheckedNeg` and `CheckedRem` traits][63] perform checked `Neg` and
|
||||||
`Rem`, returning `Some(output)` or `None` on overflow.
|
`Rem`, returning `Some(output)` or `None` on overflow.
|
||||||
|
@ -75,7 +41,7 @@
|
||||||
[63]: https://github.com/rust-num/num-traits/pull/63
|
[63]: https://github.com/rust-num/num-traits/pull/63
|
||||||
[rust#47919]: https://github.com/rust-lang/rust/pull/47919
|
[rust#47919]: https://github.com/rust-lang/rust/pull/47919
|
||||||
|
|
||||||
# Release 0.2.2 (2018-03-18)
|
# Release 0.2.2
|
||||||
|
|
||||||
- [Casting from floating point to integers now returns `None` on overflow][52],
|
- [Casting from floating point to integers now returns `None` on overflow][52],
|
||||||
avoiding [rustc's undefined behavior][rust-10184]. This applies to the `cast`
|
avoiding [rustc's undefined behavior][rust-10184]. This applies to the `cast`
|
||||||
|
@ -87,7 +53,7 @@
|
||||||
[rust-10184]: https://github.com/rust-lang/rust/issues/10184
|
[rust-10184]: https://github.com/rust-lang/rust/issues/10184
|
||||||
|
|
||||||
|
|
||||||
# Release 0.2.1 (2018-03-01)
|
# Release 0.2.1
|
||||||
|
|
||||||
- [The new `FloatCore` trait][32] offers a subset of `Float` for `#![no_std]` use.
|
- [The new `FloatCore` trait][32] offers a subset of `Float` for `#![no_std]` use.
|
||||||
[This includes everything][41] except the transcendental functions and FMA.
|
[This includes everything][41] except the transcendental functions and FMA.
|
||||||
|
@ -106,7 +72,7 @@
|
||||||
[41]: https://github.com/rust-num/num-traits/pull/41
|
[41]: https://github.com/rust-num/num-traits/pull/41
|
||||||
|
|
||||||
|
|
||||||
# Release 0.2.0 (2018-02-06)
|
# Release 0.2.0
|
||||||
|
|
||||||
- **breaking change**: [There is now a `std` feature][30], enabled by default, along
|
- **breaking change**: [There is now a `std` feature][30], enabled by default, along
|
||||||
with the implication that building *without* this feature makes this a
|
with the implication that building *without* this feature makes this a
|
||||||
|
@ -121,14 +87,14 @@
|
||||||
[30]: https://github.com/rust-num/num-traits/pull/30
|
[30]: https://github.com/rust-num/num-traits/pull/30
|
||||||
|
|
||||||
|
|
||||||
# Release 0.1.43 (2018-02-06)
|
# Release 0.1.43
|
||||||
|
|
||||||
- All items are now [re-exported from num-traits 0.2][31] for compatibility.
|
- All items are now [re-exported from num-traits 0.2][31] for compatibility.
|
||||||
|
|
||||||
[31]: https://github.com/rust-num/num-traits/pull/31
|
[31]: https://github.com/rust-num/num-traits/pull/31
|
||||||
|
|
||||||
|
|
||||||
# Release 0.1.42 (2018-01-22)
|
# Release 0.1.42
|
||||||
|
|
||||||
- [num-traits now has its own source repository][num-356] at [rust-num/num-traits][home].
|
- [num-traits now has its own source repository][num-356] at [rust-num/num-traits][home].
|
||||||
- [`ParseFloatError` now implements `Display`][22].
|
- [`ParseFloatError` now implements `Display`][22].
|
||||||
|
|
33
build.rs
33
build.rs
|
@ -1,14 +1,35 @@
|
||||||
extern crate autocfg;
|
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let ac = autocfg::new();
|
if probe("fn main() { 0i128; }") {
|
||||||
if ac.probe_type("i128") {
|
|
||||||
println!("cargo:rustc-cfg=has_i128");
|
println!("cargo:rustc-cfg=has_i128");
|
||||||
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
|
} else if env::var_os("CARGO_FEATURE_I128").is_some() {
|
||||||
panic!("i128 support was not detected!");
|
panic!("i128 support was not detected!");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
autocfg::rerun_path(file!());
|
|
||||||
|
/// Test if a code snippet can be compiled
|
||||||
|
fn probe(code: &str) -> bool {
|
||||||
|
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
|
||||||
|
let out_dir = env::var_os("OUT_DIR").expect("environment variable OUT_DIR");
|
||||||
|
|
||||||
|
let mut child = Command::new(rustc)
|
||||||
|
.arg("--out-dir")
|
||||||
|
.arg(out_dir)
|
||||||
|
.arg("--emit=obj")
|
||||||
|
.arg("-")
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.expect("rustc probe");
|
||||||
|
|
||||||
|
child
|
||||||
|
.stdin
|
||||||
|
.as_mut()
|
||||||
|
.expect("rustc stdin")
|
||||||
|
.write_all(code.as_bytes())
|
||||||
|
.expect("write rustc stdin");
|
||||||
|
|
||||||
|
child.wait().expect("rustc probe").success()
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,8 @@ cargo test --verbose
|
||||||
cargo build --verbose --no-default-features
|
cargo build --verbose --no-default-features
|
||||||
cargo test --verbose --no-default-features
|
cargo test --verbose --no-default-features
|
||||||
|
|
||||||
if [[ "$TRAVIS_RUST_VERSION" =~ ^(nightly|beta|stable)$ ]]; then
|
|
||||||
# test `i128`
|
# test `i128`
|
||||||
|
if [[ "$TRAVIS_RUST_VERSION" =~ ^(nightly|beta|stable)$ ]]; then
|
||||||
cargo build --verbose --features=i128
|
cargo build --verbose --features=i128
|
||||||
cargo test --verbose --features=i128
|
cargo test --verbose --features=i128
|
||||||
|
|
||||||
# test with std and libm (libm build fails on Rust 1.26 and earlier)
|
|
||||||
cargo build --verbose --features "libm"
|
|
||||||
cargo test --verbose --features "libm"
|
|
||||||
|
|
||||||
# test `no_std` with libm (libm build fails on Rust 1.26 and earlier)
|
|
||||||
cargo build --verbose --no-default-features --features "libm"
|
|
||||||
cargo test --verbose --no-default-features --features "libm"
|
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use core::num::Wrapping;
|
use core::{usize, u8, u16, u32, u64};
|
||||||
|
use core::{isize, i8, i16, i32, i64};
|
||||||
use core::{f32, f64};
|
use core::{f32, f64};
|
||||||
|
use core::num::Wrapping;
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
use core::{i128, u128};
|
use core::{i128, u128};
|
||||||
use core::{i16, i32, i64, i8, isize};
|
|
||||||
use core::{u16, u32, u64, u8, usize};
|
|
||||||
|
|
||||||
/// Numbers which have upper and lower bounds
|
/// Numbers which have upper and lower bounds
|
||||||
pub trait Bounded {
|
pub trait Bounded {
|
||||||
|
@ -18,16 +18,12 @@ macro_rules! bounded_impl {
|
||||||
($t:ty, $min:expr, $max:expr) => {
|
($t:ty, $min:expr, $max:expr) => {
|
||||||
impl Bounded for $t {
|
impl Bounded for $t {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn min_value() -> $t {
|
fn min_value() -> $t { $min }
|
||||||
$min
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn max_value() -> $t {
|
fn max_value() -> $t { $max }
|
||||||
$max
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bounded_impl!(usize, usize::MIN, usize::MAX);
|
bounded_impl!(usize, usize::MIN, usize::MAX);
|
||||||
|
@ -47,12 +43,8 @@ bounded_impl!(i64, i64::MIN, i64::MAX);
|
||||||
bounded_impl!(i128, i128::MIN, i128::MAX);
|
bounded_impl!(i128, i128::MIN, i128::MAX);
|
||||||
|
|
||||||
impl<T: Bounded> Bounded for Wrapping<T> {
|
impl<T: Bounded> Bounded for Wrapping<T> {
|
||||||
fn min_value() -> Self {
|
fn min_value() -> Self { Wrapping(T::min_value()) }
|
||||||
Wrapping(T::min_value())
|
fn max_value() -> Self { Wrapping(T::max_value()) }
|
||||||
}
|
|
||||||
fn max_value() -> Self {
|
|
||||||
Wrapping(T::max_value())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bounded_impl!(f32, f32::MIN, f32::MAX);
|
bounded_impl!(f32, f32::MIN, f32::MAX);
|
||||||
|
@ -67,9 +59,9 @@ macro_rules! for_each_tuple_ {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
macro_rules! for_each_tuple {
|
macro_rules! for_each_tuple {
|
||||||
($m:ident) => {
|
( $m:ident ) => (
|
||||||
for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, }
|
for_each_tuple_! { $m !! A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, }
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! bounded_tuple {
|
macro_rules! bounded_tuple {
|
||||||
|
@ -90,13 +82,14 @@ macro_rules! bounded_tuple {
|
||||||
for_each_tuple!(bounded_tuple);
|
for_each_tuple!(bounded_tuple);
|
||||||
bounded_impl!(f64, f64::MIN, f64::MAX);
|
bounded_impl!(f64, f64::MIN, f64::MAX);
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrapping_bounded() {
|
fn wrapping_bounded() {
|
||||||
macro_rules! test_wrapping_bounded {
|
macro_rules! test_wrapping_bounded {
|
||||||
($($t:ty)+) => {
|
($($t:ty)+) => {
|
||||||
$(
|
$(
|
||||||
assert_eq!(<Wrapping<$t> as Bounded>::min_value().0, <$t>::min_value());
|
assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value());
|
||||||
assert_eq!(<Wrapping<$t> as Bounded>::max_value().0, <$t>::max_value());
|
assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value());
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -110,8 +103,8 @@ fn wrapping_bounded_i128() {
|
||||||
macro_rules! test_wrapping_bounded {
|
macro_rules! test_wrapping_bounded {
|
||||||
($($t:ty)+) => {
|
($($t:ty)+) => {
|
||||||
$(
|
$(
|
||||||
assert_eq!(<Wrapping<$t> as Bounded>::min_value().0, <$t>::min_value());
|
assert_eq!(Wrapping::<$t>::min_value().0, <$t>::min_value());
|
||||||
assert_eq!(<Wrapping<$t> as Bounded>::max_value().0, <$t>::max_value());
|
assert_eq!(Wrapping::<$t>::max_value().0, <$t>::max_value());
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
119
src/cast.rs
119
src/cast.rs
|
@ -1,10 +1,10 @@
|
||||||
|
use core::{i8, i16, i32, i64, isize};
|
||||||
|
use core::{u8, u16, u32, u64, usize};
|
||||||
|
use core::{f32, f64};
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use core::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
use core::{f32, f64};
|
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
use core::{i128, u128};
|
use core::{i128, u128};
|
||||||
use core::{i16, i32, i64, i8, isize};
|
|
||||||
use core::{u16, u32, u64, u8, usize};
|
|
||||||
|
|
||||||
use float::FloatCore;
|
use float::FloatCore;
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ macro_rules! impl_to_primitive_int_to_uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_to_primitive_int {
|
macro_rules! impl_to_primitive_int {
|
||||||
($T:ident) => {
|
($T:ident) => (
|
||||||
impl ToPrimitive for $T {
|
impl ToPrimitive for $T {
|
||||||
impl_to_primitive_int_to_int! { $T:
|
impl_to_primitive_int_to_int! { $T:
|
||||||
fn to_isize -> isize;
|
fn to_isize -> isize;
|
||||||
|
@ -160,15 +160,11 @@ macro_rules! impl_to_primitive_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_f32(&self) -> Option<f32> {
|
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
|
||||||
Some(*self as f32)
|
|
||||||
}
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_f64(&self) -> Option<f64> {
|
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
|
||||||
Some(*self as f64)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_to_primitive_int!(isize);
|
impl_to_primitive_int!(isize);
|
||||||
|
@ -210,7 +206,7 @@ macro_rules! impl_to_primitive_uint_to_uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_to_primitive_uint {
|
macro_rules! impl_to_primitive_uint {
|
||||||
($T:ident) => {
|
($T:ident) => (
|
||||||
impl ToPrimitive for $T {
|
impl ToPrimitive for $T {
|
||||||
impl_to_primitive_uint_to_int! { $T:
|
impl_to_primitive_uint_to_int! { $T:
|
||||||
fn to_isize -> isize;
|
fn to_isize -> isize;
|
||||||
|
@ -233,15 +229,11 @@ macro_rules! impl_to_primitive_uint {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_f32(&self) -> Option<f32> {
|
fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
|
||||||
Some(*self as f32)
|
|
||||||
}
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_f64(&self) -> Option<f64> {
|
fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
|
||||||
Some(*self as f64)
|
|
||||||
}
|
}
|
||||||
}
|
)
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_to_primitive_uint!(usize);
|
impl_to_primitive_uint!(usize);
|
||||||
|
@ -327,7 +319,7 @@ macro_rules! impl_to_primitive_float_to_unsigned_int {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_to_primitive_float {
|
macro_rules! impl_to_primitive_float {
|
||||||
($T:ident) => {
|
($T:ident) => (
|
||||||
impl ToPrimitive for $T {
|
impl ToPrimitive for $T {
|
||||||
impl_to_primitive_float_to_signed_int! { $T:
|
impl_to_primitive_float_to_signed_int! { $T:
|
||||||
fn to_isize -> isize;
|
fn to_isize -> isize;
|
||||||
|
@ -354,7 +346,7 @@ macro_rules! impl_to_primitive_float {
|
||||||
fn to_f64 -> f64;
|
fn to_f64 -> f64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_to_primitive_float!(f32);
|
impl_to_primitive_float!(f32);
|
||||||
|
@ -471,71 +463,29 @@ pub trait FromPrimitive: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_from_primitive {
|
macro_rules! impl_from_primitive {
|
||||||
($T:ty, $to_ty:ident) => {
|
($T:ty, $to_ty:ident) => (
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
impl FromPrimitive for $T {
|
impl FromPrimitive for $T {
|
||||||
#[inline]
|
#[inline] fn from_isize(n: isize) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_isize(n: isize) -> Option<$T> {
|
#[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
|
||||||
n.$to_ty()
|
#[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
|
||||||
}
|
#[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
|
||||||
#[inline]
|
#[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_i8(n: i8) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i16(n: i16) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i32(n: i32) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_i64(n: i64) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
#[inline]
|
#[inline] fn from_i128(n: i128) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_i128(n: i128) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline] fn from_usize(n: usize) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_usize(n: usize) -> Option<$T> {
|
#[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
|
||||||
n.$to_ty()
|
#[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
|
||||||
}
|
#[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
|
||||||
#[inline]
|
#[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_u8(n: u8) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u16(n: u16) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u32(n: u32) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn from_u64(n: u64) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
#[inline]
|
#[inline] fn from_u128(n: u128) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_u128(n: u128) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
|
||||||
fn from_f32(n: f32) -> Option<$T> {
|
#[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
|
||||||
n.$to_ty()
|
|
||||||
}
|
}
|
||||||
#[inline]
|
)
|
||||||
fn from_f64(n: f64) -> Option<$T> {
|
|
||||||
n.$to_ty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_from_primitive!(isize, to_isize);
|
impl_from_primitive!(isize, to_isize);
|
||||||
|
@ -555,6 +505,7 @@ impl_from_primitive!(u128, to_u128);
|
||||||
impl_from_primitive!(f32, to_f32);
|
impl_from_primitive!(f32, to_f32);
|
||||||
impl_from_primitive!(f64, to_f64);
|
impl_from_primitive!(f64, to_f64);
|
||||||
|
|
||||||
|
|
||||||
macro_rules! impl_to_primitive_wrapping {
|
macro_rules! impl_to_primitive_wrapping {
|
||||||
($( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
|
($( $(#[$cfg:meta])* fn $method:ident -> $i:ident ; )*) => {$(
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -621,6 +572,7 @@ impl<T: FromPrimitive> FromPrimitive for Wrapping<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Cast from one machine scalar to another.
|
/// Cast from one machine scalar to another.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -644,7 +596,7 @@ pub trait NumCast: Sized + ToPrimitive {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_num_cast {
|
macro_rules! impl_num_cast {
|
||||||
($T:ty, $conv:ident) => {
|
($T:ty, $conv:ident) => (
|
||||||
impl NumCast for $T {
|
impl NumCast for $T {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -654,7 +606,7 @@ macro_rules! impl_num_cast {
|
||||||
n.$conv()
|
n.$conv()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_num_cast!(u8, to_u8);
|
impl_num_cast!(u8, to_u8);
|
||||||
|
@ -682,7 +634,7 @@ impl<T: NumCast> NumCast for Wrapping<T> {
|
||||||
|
|
||||||
/// A generic interface for casting between machine scalars with the
|
/// A generic interface for casting between machine scalars with the
|
||||||
/// `as` operator, which admits narrowing and precision loss.
|
/// `as` operator, which admits narrowing and precision loss.
|
||||||
/// Implementers of this trait `AsPrimitive` should behave like a primitive
|
/// Implementers of this trait AsPrimitive should behave like a primitive
|
||||||
/// numeric type (e.g. a newtype around another primitive), and the
|
/// numeric type (e.g. a newtype around another primitive), and the
|
||||||
/// intended conversion must never fail.
|
/// intended conversion must never fail.
|
||||||
///
|
///
|
||||||
|
@ -717,7 +669,7 @@ impl<T: NumCast> NumCast for Wrapping<T> {
|
||||||
///
|
///
|
||||||
pub trait AsPrimitive<T>: 'static + Copy
|
pub trait AsPrimitive<T>: 'static + Copy
|
||||||
where
|
where
|
||||||
T: 'static + Copy,
|
T: 'static + Copy
|
||||||
{
|
{
|
||||||
/// Convert a value to another, using the `as` operator.
|
/// Convert a value to another, using the `as` operator.
|
||||||
fn as_(self) -> T;
|
fn as_(self) -> T;
|
||||||
|
@ -760,3 +712,4 @@ impl_as_primitive!(f32 => { f32, f64 });
|
||||||
impl_as_primitive!(f64 => { f32, f64 });
|
impl_as_primitive!(f64 => { f32, f64 });
|
||||||
impl_as_primitive!(char => { char });
|
impl_as_primitive!(char => { char });
|
||||||
impl_as_primitive!(bool => {});
|
impl_as_primitive!(bool => {});
|
||||||
|
|
||||||
|
|
151
src/float.rs
151
src/float.rs
|
@ -1,15 +1,12 @@
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::num::FpCategory;
|
|
||||||
use core::ops::Neg;
|
use core::ops::Neg;
|
||||||
|
use core::num::FpCategory;
|
||||||
|
|
||||||
use core::f32;
|
use core::f32;
|
||||||
use core::f64;
|
use core::f64;
|
||||||
|
|
||||||
use {Num, NumCast, ToPrimitive};
|
use {Num, NumCast, ToPrimitive};
|
||||||
|
|
||||||
#[cfg(all(not(feature = "std"), feature = "libm"))]
|
|
||||||
use libm::{F32Ext, F64Ext};
|
|
||||||
|
|
||||||
/// Generic trait for floating point numbers that works with `no_std`.
|
/// Generic trait for floating point numbers that works with `no_std`.
|
||||||
///
|
///
|
||||||
/// This trait implements a subset of the `Float` trait.
|
/// This trait implements a subset of the `Float` trait.
|
||||||
|
@ -589,11 +586,7 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
|
||||||
if other.is_nan() {
|
if other.is_nan() {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
if self < other {
|
if self < other { self } else { other }
|
||||||
self
|
|
||||||
} else {
|
|
||||||
other
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum of the two numbers.
|
/// Returns the maximum of the two numbers.
|
||||||
|
@ -623,11 +616,7 @@ pub trait FloatCore: Num + NumCast + Neg<Output = Self> + PartialOrd + Copy {
|
||||||
if other.is_nan() {
|
if other.is_nan() {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
if self > other {
|
if self > other { self } else { other }
|
||||||
self
|
|
||||||
} else {
|
|
||||||
other
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the reciprocal (multiplicative inverse) of the number.
|
/// Returns the reciprocal (multiplicative inverse) of the number.
|
||||||
|
@ -769,8 +758,6 @@ impl FloatCore for f32 {
|
||||||
const EXP_MASK: u32 = 0x7f800000;
|
const EXP_MASK: u32 = 0x7f800000;
|
||||||
const MAN_MASK: u32 = 0x007fffff;
|
const MAN_MASK: u32 = 0x007fffff;
|
||||||
|
|
||||||
// Safety: this identical to the implementation of f32::to_bits(),
|
|
||||||
// which is only available starting at Rust 1.20
|
|
||||||
let bits: u32 = unsafe { mem::transmute(self) };
|
let bits: u32 = unsafe { mem::transmute(self) };
|
||||||
match (bits & MAN_MASK, bits & EXP_MASK) {
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||||
(0, 0) => FpCategory::Zero,
|
(0, 0) => FpCategory::Zero,
|
||||||
|
@ -843,8 +830,6 @@ impl FloatCore for f64 {
|
||||||
const EXP_MASK: u64 = 0x7ff0000000000000;
|
const EXP_MASK: u64 = 0x7ff0000000000000;
|
||||||
const MAN_MASK: u64 = 0x000fffffffffffff;
|
const MAN_MASK: u64 = 0x000fffffffffffff;
|
||||||
|
|
||||||
// Safety: this identical to the implementation of f64::to_bits(),
|
|
||||||
// which is only available starting at Rust 1.20
|
|
||||||
let bits: u64 = unsafe { mem::transmute(self) };
|
let bits: u64 = unsafe { mem::transmute(self) };
|
||||||
match (bits & MAN_MASK, bits & EXP_MASK) {
|
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||||
(0, 0) => FpCategory::Zero,
|
(0, 0) => FpCategory::Zero,
|
||||||
|
@ -900,9 +885,15 @@ impl FloatCore for f64 {
|
||||||
|
|
||||||
/// Generic trait for floating point numbers
|
/// Generic trait for floating point numbers
|
||||||
///
|
///
|
||||||
/// This trait is only available with the `std` feature, or with the `libm` feature otherwise.
|
/// This trait is only available with the `std` feature.
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
pub trait Float
|
||||||
|
: Num
|
||||||
|
+ Copy
|
||||||
|
+ NumCast
|
||||||
|
+ PartialOrd
|
||||||
|
+ Neg<Output = Self>
|
||||||
|
{
|
||||||
/// Returns the `NaN` value.
|
/// Returns the `NaN` value.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1786,6 +1777,7 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
||||||
/// ```
|
/// ```
|
||||||
fn atanh(self) -> Self;
|
fn atanh(self) -> Self;
|
||||||
|
|
||||||
|
|
||||||
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
|
/// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
|
||||||
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
|
/// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
|
||||||
///
|
///
|
||||||
|
@ -1809,8 +1801,8 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
macro_rules! float_impl_std {
|
macro_rules! float_impl {
|
||||||
($T:ident $decode:ident) => {
|
($T:ident $decode:ident) => (
|
||||||
impl Float for $T {
|
impl Float for $T {
|
||||||
constant! {
|
constant! {
|
||||||
nan() -> $T::NAN;
|
nan() -> $T::NAN;
|
||||||
|
@ -1884,93 +1876,16 @@ macro_rules! float_impl_std {
|
||||||
Self::atanh(self) -> Self;
|
Self::atanh(self) -> Self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(not(feature = "std"), feature = "libm"))]
|
|
||||||
macro_rules! float_impl_libm {
|
|
||||||
($T:ident $decode:ident $LibmImpl:ident) => {
|
|
||||||
impl Float for $T {
|
|
||||||
constant! {
|
|
||||||
nan() -> $T::NAN;
|
|
||||||
infinity() -> $T::INFINITY;
|
|
||||||
neg_infinity() -> $T::NEG_INFINITY;
|
|
||||||
neg_zero() -> -0.0;
|
|
||||||
min_value() -> $T::MIN;
|
|
||||||
min_positive_value() -> $T::MIN_POSITIVE;
|
|
||||||
epsilon() -> $T::EPSILON;
|
|
||||||
max_value() -> $T::MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
#[allow(deprecated)]
|
|
||||||
fn abs_sub(self, other: Self) -> Self {
|
|
||||||
<$T as $LibmImpl>::fdim(self, other)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn integer_decode(self) -> (u64, i16, i8) {
|
|
||||||
$decode(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
forward! {
|
|
||||||
FloatCore::is_nan(self) -> bool;
|
|
||||||
FloatCore::is_infinite(self) -> bool;
|
|
||||||
FloatCore::is_finite(self) -> bool;
|
|
||||||
FloatCore::is_normal(self) -> bool;
|
|
||||||
FloatCore::classify(self) -> FpCategory;
|
|
||||||
$LibmImpl::floor(self) -> Self;
|
|
||||||
$LibmImpl::ceil(self) -> Self;
|
|
||||||
$LibmImpl::round(self) -> Self;
|
|
||||||
$LibmImpl::trunc(self) -> Self;
|
|
||||||
$LibmImpl::fract(self) -> Self;
|
|
||||||
$LibmImpl::abs(self) -> Self;
|
|
||||||
FloatCore::signum(self) -> Self;
|
|
||||||
FloatCore::is_sign_positive(self) -> bool;
|
|
||||||
FloatCore::is_sign_negative(self) -> bool;
|
|
||||||
$LibmImpl::mul_add(self, a: Self, b: Self) -> Self;
|
|
||||||
FloatCore::recip(self) -> Self;
|
|
||||||
FloatCore::powi(self, n: i32) -> Self;
|
|
||||||
$LibmImpl::powf(self, n: Self) -> Self;
|
|
||||||
$LibmImpl::sqrt(self) -> Self;
|
|
||||||
$LibmImpl::exp(self) -> Self;
|
|
||||||
$LibmImpl::exp2(self) -> Self;
|
|
||||||
$LibmImpl::ln(self) -> Self;
|
|
||||||
$LibmImpl::log(self, base: Self) -> Self;
|
|
||||||
$LibmImpl::log2(self) -> Self;
|
|
||||||
$LibmImpl::log10(self) -> Self;
|
|
||||||
FloatCore::to_degrees(self) -> Self;
|
|
||||||
FloatCore::to_radians(self) -> Self;
|
|
||||||
FloatCore::max(self, other: Self) -> Self;
|
|
||||||
FloatCore::min(self, other: Self) -> Self;
|
|
||||||
$LibmImpl::cbrt(self) -> Self;
|
|
||||||
$LibmImpl::hypot(self, other: Self) -> Self;
|
|
||||||
$LibmImpl::sin(self) -> Self;
|
|
||||||
$LibmImpl::cos(self) -> Self;
|
|
||||||
$LibmImpl::tan(self) -> Self;
|
|
||||||
$LibmImpl::asin(self) -> Self;
|
|
||||||
$LibmImpl::acos(self) -> Self;
|
|
||||||
$LibmImpl::atan(self) -> Self;
|
|
||||||
$LibmImpl::atan2(self, other: Self) -> Self;
|
|
||||||
$LibmImpl::sin_cos(self) -> (Self, Self);
|
|
||||||
$LibmImpl::exp_m1(self) -> Self;
|
|
||||||
$LibmImpl::ln_1p(self) -> Self;
|
|
||||||
$LibmImpl::sinh(self) -> Self;
|
|
||||||
$LibmImpl::cosh(self) -> Self;
|
|
||||||
$LibmImpl::tanh(self) -> Self;
|
|
||||||
$LibmImpl::asinh(self) -> Self;
|
|
||||||
$LibmImpl::acosh(self) -> Self;
|
|
||||||
$LibmImpl::atanh(self) -> Self;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
// Safety: this identical to the implementation of f32::to_bits(),
|
|
||||||
// which is only available starting at Rust 1.20
|
|
||||||
let bits: u32 = unsafe { mem::transmute(f) };
|
let bits: u32 = unsafe { mem::transmute(f) };
|
||||||
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
|
let sign: i8 = if bits >> 31 == 0 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
};
|
||||||
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
||||||
let mantissa = if exponent == 0 {
|
let mantissa = if exponent == 0 {
|
||||||
(bits & 0x7fffff) << 1
|
(bits & 0x7fffff) << 1
|
||||||
|
@ -1983,10 +1898,12 @@ fn integer_decode_f32(f: f32) -> (u64, i16, i8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
// Safety: this identical to the implementation of f64::to_bits(),
|
|
||||||
// which is only available starting at Rust 1.20
|
|
||||||
let bits: u64 = unsafe { mem::transmute(f) };
|
let bits: u64 = unsafe { mem::transmute(f) };
|
||||||
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
|
let sign: i8 = if bits >> 63 == 0 {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
};
|
||||||
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
|
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
|
||||||
let mantissa = if exponent == 0 {
|
let mantissa = if exponent == 0 {
|
||||||
(bits & 0xfffffffffffff) << 1
|
(bits & 0xfffffffffffff) << 1
|
||||||
|
@ -1999,14 +1916,9 @@ fn integer_decode_f64(f: f64) -> (u64, i16, i8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
float_impl_std!(f32 integer_decode_f32);
|
float_impl!(f32 integer_decode_f32);
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
float_impl_std!(f64 integer_decode_f64);
|
float_impl!(f64 integer_decode_f64);
|
||||||
|
|
||||||
#[cfg(all(not(feature = "std"), feature = "libm"))]
|
|
||||||
float_impl_libm!(f32 integer_decode_f32 F32Ext);
|
|
||||||
#[cfg(all(not(feature = "std"), feature = "libm"))]
|
|
||||||
float_impl_libm!(f64 integer_decode_f64 F64Ext);
|
|
||||||
|
|
||||||
macro_rules! float_const_impl {
|
macro_rules! float_const_impl {
|
||||||
($(#[$doc:meta] $constant:ident,)+) => (
|
($(#[$doc:meta] $constant:ident,)+) => (
|
||||||
|
@ -2089,7 +2001,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
#[test]
|
#[test]
|
||||||
fn convert_deg_rad_std() {
|
fn convert_deg_rad_std() {
|
||||||
for &(deg, rad) in &DEG_RAD_PAIRS {
|
for &(deg, rad) in &DEG_RAD_PAIRS {
|
||||||
|
@ -2111,9 +2023,6 @@ mod tests {
|
||||||
fn to_degrees_rounding() {
|
fn to_degrees_rounding() {
|
||||||
use float::FloatCore;
|
use float::FloatCore;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(FloatCore::to_degrees(1_f32), 57.2957795130823208767981548141051703);
|
||||||
FloatCore::to_degrees(1_f32),
|
|
||||||
57.2957795130823208767981548141051703
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use core::num::Wrapping;
|
|
||||||
use core::ops::{Add, Mul};
|
use core::ops::{Add, Mul};
|
||||||
|
use core::num::Wrapping;
|
||||||
|
|
||||||
/// Defines an additive identity element for `Self`.
|
/// Defines an additive identity element for `Self`.
|
||||||
|
pub trait Zero: Sized + Add<Self, Output = Self> {
|
||||||
|
/// Returns the additive identity element of `Self`, `0`.
|
||||||
///
|
///
|
||||||
/// # Laws
|
/// # Laws
|
||||||
///
|
///
|
||||||
|
@ -9,8 +11,7 @@ use core::ops::{Add, Mul};
|
||||||
/// a + 0 = a ∀ a ∈ Self
|
/// a + 0 = a ∀ a ∈ Self
|
||||||
/// 0 + a = a ∀ a ∈ Self
|
/// 0 + a = a ∀ a ∈ Self
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Zero: Sized + Add<Self, Output = Self> {
|
///
|
||||||
/// Returns the additive identity element of `Self`, `0`.
|
|
||||||
/// # Purity
|
/// # Purity
|
||||||
///
|
///
|
||||||
/// This function should return the same result at all times regardless of
|
/// This function should return the same result at all times regardless of
|
||||||
|
@ -19,11 +20,6 @@ pub trait Zero: Sized + Add<Self, Output = Self> {
|
||||||
// This cannot be an associated constant, because of bignums.
|
// This cannot be an associated constant, because of bignums.
|
||||||
fn zero() -> Self;
|
fn zero() -> Self;
|
||||||
|
|
||||||
/// Sets `self` to the additive identity element of `Self`, `0`.
|
|
||||||
fn set_zero(&mut self) {
|
|
||||||
*self = Zero::zero();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `self` is equal to the additive identity.
|
/// Returns `true` if `self` is equal to the additive identity.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_zero(&self) -> bool;
|
fn is_zero(&self) -> bool;
|
||||||
|
@ -33,15 +29,11 @@ macro_rules! zero_impl {
|
||||||
($t:ty, $v:expr) => {
|
($t:ty, $v:expr) => {
|
||||||
impl Zero for $t {
|
impl Zero for $t {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> $t {
|
fn zero() -> $t { $v }
|
||||||
$v
|
|
||||||
}
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_zero(&self) -> bool {
|
fn is_zero(&self) -> bool { *self == $v }
|
||||||
*self == $v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zero_impl!(usize, 0);
|
zero_impl!(usize, 0);
|
||||||
|
@ -63,24 +55,19 @@ zero_impl!(i128, 0);
|
||||||
zero_impl!(f32, 0.0);
|
zero_impl!(f32, 0.0);
|
||||||
zero_impl!(f64, 0.0);
|
zero_impl!(f64, 0.0);
|
||||||
|
|
||||||
impl<T: Zero> Zero for Wrapping<T>
|
impl<T: Zero> Zero for Wrapping<T> where Wrapping<T>: Add<Output=Wrapping<T>> {
|
||||||
where
|
|
||||||
Wrapping<T>: Add<Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn is_zero(&self) -> bool {
|
fn is_zero(&self) -> bool {
|
||||||
self.0.is_zero()
|
self.0.is_zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_zero(&mut self) {
|
|
||||||
self.0.set_zero();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
Wrapping(T::zero())
|
Wrapping(T::zero())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Defines a multiplicative identity element for `Self`.
|
/// Defines a multiplicative identity element for `Self`.
|
||||||
|
pub trait One: Sized + Mul<Self, Output = Self> {
|
||||||
|
/// Returns the multiplicative identity element of `Self`, `1`.
|
||||||
///
|
///
|
||||||
/// # Laws
|
/// # Laws
|
||||||
///
|
///
|
||||||
|
@ -88,8 +75,6 @@ where
|
||||||
/// a * 1 = a ∀ a ∈ Self
|
/// a * 1 = a ∀ a ∈ Self
|
||||||
/// 1 * a = a ∀ a ∈ Self
|
/// 1 * a = a ∀ a ∈ Self
|
||||||
/// ```
|
/// ```
|
||||||
pub trait One: Sized + Mul<Self, Output = Self> {
|
|
||||||
/// Returns the multiplicative identity element of `Self`, `1`.
|
|
||||||
///
|
///
|
||||||
/// # Purity
|
/// # Purity
|
||||||
///
|
///
|
||||||
|
@ -99,21 +84,13 @@ pub trait One: Sized + Mul<Self, Output = Self> {
|
||||||
// This cannot be an associated constant, because of bignums.
|
// This cannot be an associated constant, because of bignums.
|
||||||
fn one() -> Self;
|
fn one() -> Self;
|
||||||
|
|
||||||
/// Sets `self` to the multiplicative identity element of `Self`, `1`.
|
|
||||||
fn set_one(&mut self) {
|
|
||||||
*self = One::one();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if `self` is equal to the multiplicative identity.
|
/// Returns `true` if `self` is equal to the multiplicative identity.
|
||||||
///
|
///
|
||||||
/// For performance reasons, it's best to implement this manually.
|
/// For performance reasons, it's best to implement this manually.
|
||||||
/// After a semver bump, this method will be required, and the
|
/// After a semver bump, this method will be required, and the
|
||||||
/// `where Self: PartialEq` bound will be removed.
|
/// `where Self: PartialEq` bound will be removed.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_one(&self) -> bool
|
fn is_one(&self) -> bool where Self: PartialEq {
|
||||||
where
|
|
||||||
Self: PartialEq,
|
|
||||||
{
|
|
||||||
*self == Self::one()
|
*self == Self::one()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,15 +99,9 @@ macro_rules! one_impl {
|
||||||
($t:ty, $v:expr) => {
|
($t:ty, $v:expr) => {
|
||||||
impl One for $t {
|
impl One for $t {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> $t {
|
fn one() -> $t { $v }
|
||||||
$v
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn is_one(&self) -> bool {
|
|
||||||
*self == $v
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
one_impl!(usize, 1);
|
one_impl!(usize, 1);
|
||||||
|
@ -152,14 +123,7 @@ one_impl!(i128, 1);
|
||||||
one_impl!(f32, 1.0);
|
one_impl!(f32, 1.0);
|
||||||
one_impl!(f64, 1.0);
|
one_impl!(f64, 1.0);
|
||||||
|
|
||||||
impl<T: One> One for Wrapping<T>
|
impl<T: One> One for Wrapping<T> where Wrapping<T>: Mul<Output=Wrapping<T>> {
|
||||||
where
|
|
||||||
Wrapping<T>: Mul<Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn set_one(&mut self) {
|
|
||||||
self.0.set_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn one() -> Self {
|
fn one() -> Self {
|
||||||
Wrapping(T::one())
|
Wrapping(T::one())
|
||||||
}
|
}
|
||||||
|
@ -168,16 +132,11 @@ where
|
||||||
// Some helper functions provided for backwards compatibility.
|
// Some helper functions provided for backwards compatibility.
|
||||||
|
|
||||||
/// Returns the additive identity, `0`.
|
/// Returns the additive identity, `0`.
|
||||||
#[inline(always)]
|
#[inline(always)] pub fn zero<T: Zero>() -> T { Zero::zero() }
|
||||||
pub fn zero<T: Zero>() -> T {
|
|
||||||
Zero::zero()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the multiplicative identity, `1`.
|
/// Returns the multiplicative identity, `1`.
|
||||||
#[inline(always)]
|
#[inline(always)] pub fn one<T: One>() -> T { One::one() }
|
||||||
pub fn one<T: One>() -> T {
|
|
||||||
One::one()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrapping_identities() {
|
fn wrapping_identities() {
|
||||||
|
|
51
src/int.rs
51
src/int.rs
|
@ -1,45 +1,16 @@
|
||||||
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
|
use core::ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
|
||||||
|
|
||||||
|
use {Num, NumCast};
|
||||||
use bounds::Bounded;
|
use bounds::Bounded;
|
||||||
use ops::checked::*;
|
use ops::checked::*;
|
||||||
use ops::saturating::Saturating;
|
use ops::saturating::Saturating;
|
||||||
use {Num, NumCast};
|
|
||||||
|
|
||||||
/// Generic trait for primitive integers.
|
pub trait PrimInt
|
||||||
///
|
: Sized
|
||||||
/// The `PrimInt` trait is an abstraction over the builtin primitive integer types (e.g., `u8`,
|
|
||||||
/// `u32`, `isize`, `i128`, ...). It inherits the basic numeric traits and extends them with
|
|
||||||
/// bitwise operators and non-wrapping arithmetic.
|
|
||||||
///
|
|
||||||
/// The trait explicitly inherits `Copy`, `Eq`, `Ord`, and `Sized`. The intention is that all
|
|
||||||
/// types implementing this trait behave like primitive types that are passed by value by default
|
|
||||||
/// and behave like builtin integers. Furthermore, the types are expected to expose the integer
|
|
||||||
/// value in binary representation and support bitwise operators. The standard bitwise operations
|
|
||||||
/// (e.g., bitwise-and, bitwise-or, right-shift, left-shift) are inherited and the trait extends
|
|
||||||
/// these with introspective queries (e.g., `PrimInt::count_ones()`, `PrimInt::leading_zeros()`),
|
|
||||||
/// bitwise combinators (e.g., `PrimInt::rotate_left()`), and endianness converters (e.g.,
|
|
||||||
/// `PrimInt::to_be()`).
|
|
||||||
///
|
|
||||||
/// All `PrimInt` types are expected to be fixed-width binary integers. The width can be queried
|
|
||||||
/// via `T::zero().count_zeros()`. The trait currently lacks a way to query the width at
|
|
||||||
/// compile-time.
|
|
||||||
///
|
|
||||||
/// While a default implementation for all builtin primitive integers is provided, the trait is in
|
|
||||||
/// no way restricted to these. Other integer types that fulfil the requirements are free to
|
|
||||||
/// implement the trait was well.
|
|
||||||
///
|
|
||||||
/// This trait and many of the method names originate in the unstable `core::num::Int` trait from
|
|
||||||
/// the rust standard library. The original trait was never stabilized and thus removed from the
|
|
||||||
/// standard library.
|
|
||||||
pub trait PrimInt:
|
|
||||||
Sized
|
|
||||||
+ Copy
|
+ Copy
|
||||||
+ Num
|
+ Num + NumCast
|
||||||
+ NumCast
|
|
||||||
+ Bounded
|
+ Bounded
|
||||||
+ PartialOrd
|
+ PartialOrd + Ord + Eq
|
||||||
+ Ord
|
|
||||||
+ Eq
|
|
||||||
+ Not<Output=Self>
|
+ Not<Output=Self>
|
||||||
+ BitAnd<Output=Self>
|
+ BitAnd<Output=Self>
|
||||||
+ BitOr<Output=Self>
|
+ BitOr<Output=Self>
|
||||||
|
@ -197,10 +168,10 @@ pub trait PrimInt:
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::PrimInt;
|
/// use num_traits::PrimInt;
|
||||||
///
|
///
|
||||||
/// let n = -8i8; // 0b11111000
|
/// let n = 0xFEDCBA9876543210i64;
|
||||||
/// let m = 62i8; // 0b00111110
|
/// let m = 0x000FEDCBA9876543i64;
|
||||||
///
|
///
|
||||||
/// assert_eq!(n.unsigned_shr(2), m);
|
/// assert_eq!(n.unsigned_shr(12), m);
|
||||||
/// ```
|
/// ```
|
||||||
fn unsigned_shr(self, n: u32) -> Self;
|
fn unsigned_shr(self, n: u32) -> Self;
|
||||||
|
|
||||||
|
@ -307,7 +278,7 @@ pub trait PrimInt:
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! prim_int_impl {
|
macro_rules! prim_int_impl {
|
||||||
($T:ty, $S:ty, $U:ty) => {
|
($T:ty, $S:ty, $U:ty) => (
|
||||||
impl PrimInt for $T {
|
impl PrimInt for $T {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn count_ones(self) -> u32 {
|
fn count_ones(self) -> u32 {
|
||||||
|
@ -389,7 +360,7 @@ macro_rules! prim_int_impl {
|
||||||
<$T>::pow(self, exp)
|
<$T>::pow(self, exp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// prim_int_impl!(type, signed, unsigned);
|
// prim_int_impl!(type, signed, unsigned);
|
||||||
|
|
200
src/lib.rs
200
src/lib.rs
|
@ -15,54 +15,53 @@
|
||||||
//! The `num-traits` crate is tested for rustc 1.8 and greater.
|
//! The `num-traits` crate is tested for rustc 1.8 and greater.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
|
#![doc(html_root_url = "https://docs.rs/num-traits/0.2")]
|
||||||
|
|
||||||
#![deny(unconditional_recursion)]
|
#![deny(unconditional_recursion)]
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
extern crate std;
|
extern crate std;
|
||||||
|
|
||||||
// Only `no_std` builds actually use `libm`.
|
use core::ops::{Add, Sub, Mul, Div, Rem};
|
||||||
#[cfg(all(not(feature = "std"), feature = "libm"))]
|
use core::ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
|
||||||
extern crate libm;
|
|
||||||
|
|
||||||
use core::fmt;
|
|
||||||
use core::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
use core::ops::{Add, Div, Mul, Rem, Sub};
|
use core::fmt;
|
||||||
use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
|
|
||||||
|
|
||||||
pub use bounds::Bounded;
|
pub use bounds::Bounded;
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
pub use float::Float;
|
pub use float::Float;
|
||||||
pub use float::FloatConst;
|
pub use float::FloatConst;
|
||||||
// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
// pub use real::{FloatCore, Real}; // NOTE: Don't do this, it breaks `use num_traits::*;`.
|
||||||
pub use cast::{cast, AsPrimitive, FromPrimitive, NumCast, ToPrimitive};
|
pub use identities::{Zero, One, zero, one};
|
||||||
pub use identities::{one, zero, One, Zero};
|
|
||||||
pub use int::PrimInt;
|
|
||||||
pub use ops::checked::{
|
|
||||||
CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedRem, CheckedShl, CheckedShr, CheckedSub,
|
|
||||||
};
|
|
||||||
pub use ops::inv::Inv;
|
pub use ops::inv::Inv;
|
||||||
|
pub use ops::checked::{CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
|
||||||
|
CheckedRem, CheckedNeg, CheckedShl, CheckedShr};
|
||||||
|
pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingSub};
|
||||||
pub use ops::mul_add::{MulAdd, MulAddAssign};
|
pub use ops::mul_add::{MulAdd, MulAddAssign};
|
||||||
pub use ops::saturating::Saturating;
|
pub use ops::saturating::Saturating;
|
||||||
pub use ops::wrapping::{WrappingAdd, WrappingMul, WrappingShl, WrappingShr, WrappingSub};
|
pub use sign::{Signed, Unsigned, abs, abs_sub, signum};
|
||||||
pub use pow::{checked_pow, pow, Pow};
|
pub use cast::{AsPrimitive, FromPrimitive, ToPrimitive, NumCast, cast};
|
||||||
pub use sign::{abs, abs_sub, signum, Signed, Unsigned};
|
pub use int::PrimInt;
|
||||||
|
pub use pow::{Pow, pow, checked_pow};
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod bounds;
|
|
||||||
pub mod cast;
|
|
||||||
pub mod float;
|
|
||||||
pub mod identities;
|
pub mod identities;
|
||||||
pub mod int;
|
|
||||||
pub mod ops;
|
|
||||||
pub mod pow;
|
|
||||||
pub mod real;
|
|
||||||
pub mod sign;
|
pub mod sign;
|
||||||
|
pub mod ops;
|
||||||
|
pub mod bounds;
|
||||||
|
pub mod float;
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
pub mod real;
|
||||||
|
pub mod cast;
|
||||||
|
pub mod int;
|
||||||
|
pub mod pow;
|
||||||
|
|
||||||
/// The base trait for numeric types, covering `0` and `1` values,
|
/// The base trait for numeric types, covering `0` and `1` values,
|
||||||
/// comparisons, basic numeric operations, and string conversion.
|
/// comparisons, basic numeric operations, and string conversion.
|
||||||
pub trait Num: PartialEq + Zero + One + NumOps {
|
pub trait Num: PartialEq + Zero + One + NumOps
|
||||||
|
{
|
||||||
type FromStrRadixErr;
|
type FromStrRadixErr;
|
||||||
|
|
||||||
/// Convert from a string and radix <= 36.
|
/// Convert from a string and radix <= 36.
|
||||||
|
@ -84,23 +83,21 @@ pub trait Num: PartialEq + Zero + One + NumOps {
|
||||||
/// The trait for types implementing basic numeric operations
|
/// The trait for types implementing basic numeric operations
|
||||||
///
|
///
|
||||||
/// This is automatically implemented for types which implement the operators.
|
/// This is automatically implemented for types which implement the operators.
|
||||||
pub trait NumOps<Rhs = Self, Output = Self>:
|
pub trait NumOps<Rhs = Self, Output = Self>
|
||||||
Add<Rhs, Output = Output>
|
: Add<Rhs, Output = Output>
|
||||||
+ Sub<Rhs, Output = Output>
|
+ Sub<Rhs, Output = Output>
|
||||||
+ Mul<Rhs, Output = Output>
|
+ Mul<Rhs, Output = Output>
|
||||||
+ Div<Rhs, Output = Output>
|
+ Div<Rhs, Output = Output>
|
||||||
+ Rem<Rhs, Output = Output>
|
+ Rem<Rhs, Output = Output>
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, Rhs, Output> NumOps<Rhs, Output> for T where
|
impl<T, Rhs, Output> NumOps<Rhs, Output> for T
|
||||||
T: Add<Rhs, Output = Output>
|
where T: Add<Rhs, Output = Output>
|
||||||
+ Sub<Rhs, Output = Output>
|
+ Sub<Rhs, Output = Output>
|
||||||
+ Mul<Rhs, Output = Output>
|
+ Mul<Rhs, Output = Output>
|
||||||
+ Div<Rhs, Output = Output>
|
+ Div<Rhs, Output = Output>
|
||||||
+ Rem<Rhs, Output = Output>
|
+ Rem<Rhs, Output = Output>
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
/// The trait for `Num` types which also implement numeric operations taking
|
/// The trait for `Num` types which also implement numeric operations taking
|
||||||
/// the second operand by reference.
|
/// the second operand by reference.
|
||||||
|
@ -119,15 +116,21 @@ impl<T, Base> RefNum<Base> for T where T: NumOps<Base, Base> + for<'r> NumOps<&'
|
||||||
/// The trait for types implementing numeric assignment operators (like `+=`).
|
/// The trait for types implementing numeric assignment operators (like `+=`).
|
||||||
///
|
///
|
||||||
/// This is automatically implemented for types which implement the operators.
|
/// This is automatically implemented for types which implement the operators.
|
||||||
pub trait NumAssignOps<Rhs = Self>:
|
pub trait NumAssignOps<Rhs = Self>
|
||||||
AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
|
: AddAssign<Rhs>
|
||||||
{
|
+ SubAssign<Rhs>
|
||||||
}
|
+ MulAssign<Rhs>
|
||||||
|
+ DivAssign<Rhs>
|
||||||
|
+ RemAssign<Rhs>
|
||||||
|
{}
|
||||||
|
|
||||||
impl<T, Rhs> NumAssignOps<Rhs> for T where
|
impl<T, Rhs> NumAssignOps<Rhs> for T
|
||||||
T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>
|
where T: AddAssign<Rhs>
|
||||||
{
|
+ SubAssign<Rhs>
|
||||||
}
|
+ MulAssign<Rhs>
|
||||||
|
+ DivAssign<Rhs>
|
||||||
|
+ RemAssign<Rhs>
|
||||||
|
{}
|
||||||
|
|
||||||
/// The trait for `Num` types which also implement assignment operators.
|
/// The trait for `Num` types which also implement assignment operators.
|
||||||
///
|
///
|
||||||
|
@ -142,6 +145,7 @@ impl<T> NumAssign for T where T: Num + NumAssignOps {}
|
||||||
pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
|
pub trait NumAssignRef: NumAssign + for<'r> NumAssignOps<&'r Self> {}
|
||||||
impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
|
impl<T> NumAssignRef for T where T: NumAssign + for<'r> NumAssignOps<&'r T> {}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! int_trait_impl {
|
macro_rules! int_trait_impl {
|
||||||
($name:ident for $($t:ty)*) => ($(
|
($name:ident for $($t:ty)*) => ($(
|
||||||
impl $name for $t {
|
impl $name for $t {
|
||||||
|
@ -160,12 +164,9 @@ int_trait_impl!(Num for usize u8 u16 u32 u64 isize i8 i16 i32 i64);
|
||||||
int_trait_impl!(Num for u128 i128);
|
int_trait_impl!(Num for u128 i128);
|
||||||
|
|
||||||
impl<T: Num> Num for Wrapping<T>
|
impl<T: Num> Num for Wrapping<T>
|
||||||
where
|
where Wrapping<T>:
|
||||||
Wrapping<T>: Add<Output = Wrapping<T>>
|
Add<Output = Wrapping<T>> + Sub<Output = Wrapping<T>>
|
||||||
+ Sub<Output = Wrapping<T>>
|
+ Mul<Output = Wrapping<T>> + Div<Output = Wrapping<T>> + Rem<Output = Wrapping<T>>
|
||||||
+ Mul<Output = Wrapping<T>>
|
|
||||||
+ Div<Output = Wrapping<T>>
|
|
||||||
+ Rem<Output = Wrapping<T>>,
|
|
||||||
{
|
{
|
||||||
type FromStrRadixErr = T::FromStrRadixErr;
|
type FromStrRadixErr = T::FromStrRadixErr;
|
||||||
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
|
||||||
|
@ -173,6 +174,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum FloatErrorKind {
|
pub enum FloatErrorKind {
|
||||||
Empty,
|
Empty,
|
||||||
|
@ -219,12 +221,7 @@ macro_rules! float_trait_impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slice_shift_char(src: &str) -> Option<(char, &str)> {
|
fn slice_shift_char(src: &str) -> Option<(char, &str)> {
|
||||||
let mut chars = src.chars();
|
src.chars().nth(0).map(|ch| (ch, &src[1..]))
|
||||||
if let Some(ch) = chars.next() {
|
|
||||||
Some((ch, chars.as_str()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let (is_positive, src) = match slice_shift_char(src) {
|
let (is_positive, src) = match slice_shift_char(src) {
|
||||||
|
@ -367,8 +364,6 @@ float_trait_impl!(Num for f32 f64);
|
||||||
/// If input is less than min then this returns min.
|
/// If input is less than min then this returns min.
|
||||||
/// If input is greater than max then this returns max.
|
/// If input is greater than max then this returns max.
|
||||||
/// Otherwise this returns input.
|
/// Otherwise this returns input.
|
||||||
///
|
|
||||||
/// **Panics** in debug mode if `!(min <= max)`.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
|
pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
|
||||||
debug_assert!(min <= max, "min must be less than or equal to max");
|
debug_assert!(min <= max, "min must be less than or equal to max");
|
||||||
|
@ -381,97 +376,17 @@ pub fn clamp<T: PartialOrd>(input: T, min: T, max: T) -> T {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value bounded by a minimum value
|
|
||||||
///
|
|
||||||
/// If input is less than min then this returns min.
|
|
||||||
/// Otherwise this returns input.
|
|
||||||
/// `clamp_min(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::min(std::f32::NAN, 1.0)`.
|
|
||||||
///
|
|
||||||
/// **Panics** in debug mode if `!(min == min)`. (This occurs if `min` is `NAN`.)
|
|
||||||
#[inline]
|
|
||||||
pub fn clamp_min<T: PartialOrd>(input: T, min: T) -> T {
|
|
||||||
debug_assert!(min == min, "min must not be NAN");
|
|
||||||
if input < min {
|
|
||||||
min
|
|
||||||
} else {
|
|
||||||
input
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A value bounded by a maximum value
|
|
||||||
///
|
|
||||||
/// If input is greater than max then this returns max.
|
|
||||||
/// Otherwise this returns input.
|
|
||||||
/// `clamp_max(std::f32::NAN, 1.0)` preserves `NAN` different from `f32::max(std::f32::NAN, 1.0)`.
|
|
||||||
///
|
|
||||||
/// **Panics** in debug mode if `!(max == max)`. (This occurs if `max` is `NAN`.)
|
|
||||||
#[inline]
|
|
||||||
pub fn clamp_max<T: PartialOrd>(input: T, max: T) -> T {
|
|
||||||
debug_assert!(max == max, "max must not be NAN");
|
|
||||||
if input > max {
|
|
||||||
max
|
|
||||||
} else {
|
|
||||||
input
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn clamp_test() {
|
fn clamp_test() {
|
||||||
// Int test
|
// Int test
|
||||||
assert_eq!(1, clamp(1, -1, 2));
|
assert_eq!(1, clamp(1, -1, 2));
|
||||||
assert_eq!(-1, clamp(-2, -1, 2));
|
assert_eq!(-1, clamp(-2, -1, 2));
|
||||||
assert_eq!(2, clamp(3, -1, 2));
|
assert_eq!(2, clamp(3, -1, 2));
|
||||||
assert_eq!(1, clamp_min(1, -1));
|
|
||||||
assert_eq!(-1, clamp_min(-2, -1));
|
|
||||||
assert_eq!(-1, clamp_max(1, -1));
|
|
||||||
assert_eq!(-2, clamp_max(-2, -1));
|
|
||||||
|
|
||||||
// Float test
|
// Float test
|
||||||
assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
|
assert_eq!(1.0, clamp(1.0, -1.0, 2.0));
|
||||||
assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
|
assert_eq!(-1.0, clamp(-2.0, -1.0, 2.0));
|
||||||
assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
|
assert_eq!(2.0, clamp(3.0, -1.0, 2.0));
|
||||||
assert_eq!(1.0, clamp_min(1.0, -1.0));
|
|
||||||
assert_eq!(-1.0, clamp_min(-2.0, -1.0));
|
|
||||||
assert_eq!(-1.0, clamp_max(1.0, -1.0));
|
|
||||||
assert_eq!(-2.0, clamp_max(-2.0, -1.0));
|
|
||||||
assert!(clamp(::core::f32::NAN, -1.0, 1.0).is_nan());
|
|
||||||
assert!(clamp_min(::core::f32::NAN, 1.0).is_nan());
|
|
||||||
assert!(clamp_max(::core::f32::NAN, 1.0).is_nan());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn clamp_nan_min() {
|
|
||||||
clamp(0., ::core::f32::NAN, 1.);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn clamp_nan_max() {
|
|
||||||
clamp(0., -1., ::core::f32::NAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn clamp_nan_min_max() {
|
|
||||||
clamp(0., ::core::f32::NAN, ::core::f32::NAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn clamp_min_nan_min() {
|
|
||||||
clamp_min(0., ::core::f32::NAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
fn clamp_max_nan_max() {
|
|
||||||
clamp_max(0., ::core::f32::NAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -485,15 +400,6 @@ fn from_str_radix_unwrap() {
|
||||||
assert_eq!(f, 0.0);
|
assert_eq!(f, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn from_str_radix_multi_byte_fail() {
|
|
||||||
// Ensure parsing doesn't panic, even on invalid sign characters
|
|
||||||
assert!(f32::from_str_radix("™0.2", 10).is_err());
|
|
||||||
|
|
||||||
// Even when parsing the exponent sign
|
|
||||||
assert!(f32::from_str_radix("0.2E™1", 10).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn wrapping_is_num() {
|
fn wrapping_is_num() {
|
||||||
fn require_num<T: Num>(_: &T) {}
|
fn require_num<T: Num>(_: &T) {}
|
||||||
|
@ -536,8 +442,7 @@ fn check_numref_ops() {
|
||||||
#[test]
|
#[test]
|
||||||
fn check_refnum_ops() {
|
fn check_refnum_ops() {
|
||||||
fn compute<T: Copy>(x: &T, y: T) -> T
|
fn compute<T: Copy>(x: &T, y: T) -> T
|
||||||
where
|
where for<'a> &'a T: RefNum<T>
|
||||||
for<'a> &'a T: RefNum<T>,
|
|
||||||
{
|
{
|
||||||
&(&(&(&(x * y) / y) % y) + y) - y
|
&(&(&(&(x * y) / y) % y) + y) - y
|
||||||
}
|
}
|
||||||
|
@ -547,8 +452,7 @@ fn check_refnum_ops() {
|
||||||
#[test]
|
#[test]
|
||||||
fn check_refref_ops() {
|
fn check_refref_ops() {
|
||||||
fn compute<T>(x: &T, y: &T) -> T
|
fn compute<T>(x: &T, y: &T) -> T
|
||||||
where
|
where for<'a> &'a T: RefNum<T>
|
||||||
for<'a> &'a T: RefNum<T>,
|
|
||||||
{
|
{
|
||||||
&(&(&(&(x * y) / y) % y) + y) - y
|
&(&(&(&(x * y) / y) % y) + y) - y
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use core::ops::{Add, Div, Mul, Rem, Shl, Shr, Sub};
|
use core::ops::{Add, Sub, Mul, Div, Rem, Shl, Shr};
|
||||||
|
|
||||||
/// Performs addition that returns `None` instead of wrapping around on
|
/// Performs addition that returns `None` instead of wrapping around on
|
||||||
/// overflow.
|
/// overflow.
|
||||||
|
@ -16,7 +16,7 @@ macro_rules! checked_impl {
|
||||||
<$t>::$method(*self, *v)
|
<$t>::$method(*self, *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checked_impl!(CheckedAdd, checked_add, u8);
|
checked_impl!(CheckedAdd, checked_add, u8);
|
||||||
|
@ -155,7 +155,7 @@ macro_rules! checked_impl_unary {
|
||||||
<$t>::$method(*self)
|
<$t>::$method(*self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs negation that returns `None` if the result can't be represented.
|
/// Performs negation that returns `None` if the result can't be represented.
|
||||||
|
@ -195,11 +195,10 @@ checked_impl_unary!(CheckedNeg, checked_neg, isize);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
checked_impl_unary!(CheckedNeg, checked_neg, i128);
|
checked_impl_unary!(CheckedNeg, checked_neg, i128);
|
||||||
|
|
||||||
/// Performs a left shift that returns `None` on shifts larger than
|
/// Performs a left shift that returns `None` on overflow.
|
||||||
/// the type width.
|
|
||||||
pub trait CheckedShl: Sized + Shl<u32, Output=Self> {
|
pub trait CheckedShl: Sized + Shl<u32, Output=Self> {
|
||||||
/// Checked shift left. Computes `self << rhs`, returning `None`
|
/// Shifts a number to the left, checking for overflow. If overflow happens,
|
||||||
/// if `rhs` is larger than or equal to the number of bits in `self`.
|
/// `None` is returned.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::CheckedShl;
|
/// use num_traits::CheckedShl;
|
||||||
|
@ -222,7 +221,7 @@ macro_rules! checked_shift_impl {
|
||||||
<$t>::$method(*self, rhs)
|
<$t>::$method(*self, rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checked_shift_impl!(CheckedShl, checked_shl, u8);
|
checked_shift_impl!(CheckedShl, checked_shl, u8);
|
||||||
|
@ -241,11 +240,10 @@ checked_shift_impl!(CheckedShl, checked_shl, isize);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
checked_shift_impl!(CheckedShl, checked_shl, i128);
|
checked_shift_impl!(CheckedShl, checked_shl, i128);
|
||||||
|
|
||||||
/// Performs a right shift that returns `None` on shifts larger than
|
/// Performs a right shift that returns `None` on overflow.
|
||||||
/// the type width.
|
|
||||||
pub trait CheckedShr: Sized + Shr<u32, Output=Self> {
|
pub trait CheckedShr: Sized + Shr<u32, Output=Self> {
|
||||||
/// Checked shift right. Computes `self >> rhs`, returning `None`
|
/// Shifts a number to the left, checking for overflow. If overflow happens,
|
||||||
/// if `rhs` is larger than or equal to the number of bits in `self`.
|
/// `None` is returned.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use num_traits::CheckedShr;
|
/// use num_traits::CheckedShr;
|
||||||
|
|
|
@ -20,28 +20,20 @@ pub trait Inv {
|
||||||
impl Inv for f32 {
|
impl Inv for f32 {
|
||||||
type Output = f32;
|
type Output = f32;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inv(self) -> f32 {
|
fn inv(self) -> f32 { 1.0 / self }
|
||||||
1.0 / self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl Inv for f64 {
|
impl Inv for f64 {
|
||||||
type Output = f64;
|
type Output = f64;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inv(self) -> f64 {
|
fn inv(self) -> f64 { 1.0 / self }
|
||||||
1.0 / self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<'a> Inv for &'a f32 {
|
impl<'a> Inv for &'a f32 {
|
||||||
type Output = f32;
|
type Output = f32;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inv(self) -> f32 {
|
fn inv(self) -> f32 { 1.0 / *self }
|
||||||
1.0 / *self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
impl<'a> Inv for &'a f64 {
|
impl<'a> Inv for &'a f64 {
|
||||||
type Output = f64;
|
type Output = f64;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inv(self) -> f64 {
|
fn inv(self) -> f64 { 1.0 / *self }
|
||||||
1.0 / *self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
pub mod saturating;
|
||||||
pub mod checked;
|
pub mod checked;
|
||||||
|
pub mod wrapping;
|
||||||
pub mod inv;
|
pub mod inv;
|
||||||
pub mod mul_add;
|
pub mod mul_add;
|
||||||
pub mod saturating;
|
|
||||||
pub mod wrapping;
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
/// // 100.0
|
/// // 100.0
|
||||||
/// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
|
/// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
|
||||||
///
|
///
|
||||||
/// assert!(abs_difference <= 100.0 * f32::EPSILON);
|
/// assert!(abs_difference <= f32::EPSILON);
|
||||||
/// ```
|
/// ```
|
||||||
pub trait MulAdd<A = Self, B = Self> {
|
pub trait MulAdd<A = Self, B = Self> {
|
||||||
/// The resulting type after applying the fused multiply-add.
|
/// The resulting type after applying the fused multiply-add.
|
||||||
|
@ -34,23 +34,23 @@ pub trait MulAddAssign<A = Self, B = Self> {
|
||||||
fn mul_add_assign(&mut self, a: A, b: B);
|
fn mul_add_assign(&mut self, a: A, b: B);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
impl MulAdd<f32, f32> for f32 {
|
impl MulAdd<f32, f32> for f32 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_add(self, a: Self, b: Self) -> Self::Output {
|
fn mul_add(self, a: Self, b: Self) -> Self::Output {
|
||||||
<Self as ::Float>::mul_add(self, a, b)
|
f32::mul_add(self, a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
impl MulAdd<f64, f64> for f64 {
|
impl MulAdd<f64, f64> for f64 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_add(self, a: Self, b: Self) -> Self::Output {
|
fn mul_add(self, a: Self, b: Self) -> Self::Output {
|
||||||
<Self as ::Float>::mul_add(self, a, b)
|
f64::mul_add(self, a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,19 +71,19 @@ mul_add_impl!(MulAdd for isize usize i8 u8 i16 u16 i32 u32 i64 u64);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
mul_add_impl!(MulAdd for i128 u128);
|
mul_add_impl!(MulAdd for i128 u128);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
impl MulAddAssign<f32, f32> for f32 {
|
impl MulAddAssign<f32, f32> for f32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_add_assign(&mut self, a: Self, b: Self) {
|
fn mul_add_assign(&mut self, a: Self, b: Self) {
|
||||||
*self = <Self as ::Float>::mul_add(*self, a, b)
|
*self = f32::mul_add(*self, a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
impl MulAddAssign<f64, f64> for f64 {
|
impl MulAddAssign<f64, f64> for f64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn mul_add_assign(&mut self, a: Self, b: Self) {
|
fn mul_add_assign(&mut self, a: Self, b: Self) {
|
||||||
*self = <Self as ::Float>::mul_add(*self, a, b)
|
*self = f64::mul_add(*self, a, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ mod tests {
|
||||||
|
|
||||||
let abs_difference = (MulAdd::mul_add(m, x, b) - (m*x + b)).abs();
|
let abs_difference = (MulAdd::mul_add(m, x, b) - (m*x + b)).abs();
|
||||||
|
|
||||||
assert!(abs_difference <= 46.4 * $t::EPSILON);
|
assert!(abs_difference <= $t::EPSILON);
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use core::ops::{Add, Sub, Mul};
|
||||||
use core::num::Wrapping;
|
use core::num::Wrapping;
|
||||||
use core::ops::{Add, Mul, Shl, Shr, Sub};
|
|
||||||
|
|
||||||
macro_rules! wrapping_impl {
|
macro_rules! wrapping_impl {
|
||||||
($trait_name:ident, $method:ident, $t:ty) => {
|
($trait_name:ident, $method:ident, $t:ty) => {
|
||||||
|
@ -17,7 +17,7 @@ macro_rules! wrapping_impl {
|
||||||
<$t>::$method(*self, *v)
|
<$t>::$method(*self, *v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs addition that wraps around on overflow.
|
/// Performs addition that wraps around on overflow.
|
||||||
|
@ -89,156 +89,35 @@ wrapping_impl!(WrappingMul, wrapping_mul, isize);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
wrapping_impl!(WrappingMul, wrapping_mul, i128);
|
wrapping_impl!(WrappingMul, wrapping_mul, i128);
|
||||||
|
|
||||||
macro_rules! wrapping_shift_impl {
|
|
||||||
($trait_name:ident, $method:ident, $t:ty) => {
|
|
||||||
impl $trait_name for $t {
|
|
||||||
#[inline]
|
|
||||||
fn $method(&self, rhs: u32) -> $t {
|
|
||||||
<$t>::$method(*self, rhs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs a left shift that does not panic.
|
|
||||||
pub trait WrappingShl: Sized + Shl<usize, Output = Self> {
|
|
||||||
/// Panic-free bitwise shift-left; yields `self << mask(rhs)`,
|
|
||||||
/// where `mask` removes any high order bits of `rhs` that would
|
|
||||||
/// cause the shift to exceed the bitwidth of the type.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use num_traits::WrappingShl;
|
|
||||||
///
|
|
||||||
/// let x: u16 = 0x0001;
|
|
||||||
///
|
|
||||||
/// assert_eq!(WrappingShl::wrapping_shl(&x, 0), 0x0001);
|
|
||||||
/// assert_eq!(WrappingShl::wrapping_shl(&x, 1), 0x0002);
|
|
||||||
/// assert_eq!(WrappingShl::wrapping_shl(&x, 15), 0x8000);
|
|
||||||
/// assert_eq!(WrappingShl::wrapping_shl(&x, 16), 0x0001);
|
|
||||||
/// ```
|
|
||||||
fn wrapping_shl(&self, rhs: u32) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, u8);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, u16);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, u32);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, u64);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, usize);
|
|
||||||
#[cfg(has_i128)]
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, u128);
|
|
||||||
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, i8);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, i16);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, i32);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, i64);
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, isize);
|
|
||||||
#[cfg(has_i128)]
|
|
||||||
wrapping_shift_impl!(WrappingShl, wrapping_shl, i128);
|
|
||||||
|
|
||||||
/// Performs a right shift that does not panic.
|
|
||||||
pub trait WrappingShr: Sized + Shr<usize, Output = Self> {
|
|
||||||
/// Panic-free bitwise shift-right; yields `self >> mask(rhs)`,
|
|
||||||
/// where `mask` removes any high order bits of `rhs` that would
|
|
||||||
/// cause the shift to exceed the bitwidth of the type.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use num_traits::WrappingShr;
|
|
||||||
///
|
|
||||||
/// let x: u16 = 0x8000;
|
|
||||||
///
|
|
||||||
/// assert_eq!(WrappingShr::wrapping_shr(&x, 0), 0x8000);
|
|
||||||
/// assert_eq!(WrappingShr::wrapping_shr(&x, 1), 0x4000);
|
|
||||||
/// assert_eq!(WrappingShr::wrapping_shr(&x, 15), 0x0001);
|
|
||||||
/// assert_eq!(WrappingShr::wrapping_shr(&x, 16), 0x8000);
|
|
||||||
/// ```
|
|
||||||
fn wrapping_shr(&self, rhs: u32) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, u8);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, u16);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, u32);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, u64);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, usize);
|
|
||||||
#[cfg(has_i128)]
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, u128);
|
|
||||||
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, i8);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, i16);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, i32);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, i64);
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, isize);
|
|
||||||
#[cfg(has_i128)]
|
|
||||||
wrapping_shift_impl!(WrappingShr, wrapping_shr, i128);
|
|
||||||
|
|
||||||
// Well this is a bit funny, but all the more appropriate.
|
// Well this is a bit funny, but all the more appropriate.
|
||||||
impl<T: WrappingAdd> WrappingAdd for Wrapping<T>
|
impl<T: WrappingAdd> WrappingAdd for Wrapping<T> where Wrapping<T>: Add<Output = Wrapping<T>> {
|
||||||
where
|
|
||||||
Wrapping<T>: Add<Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn wrapping_add(&self, v: &Self) -> Self {
|
fn wrapping_add(&self, v: &Self) -> Self {
|
||||||
Wrapping(self.0.wrapping_add(&v.0))
|
Wrapping(self.0.wrapping_add(&v.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: WrappingSub> WrappingSub for Wrapping<T>
|
impl<T: WrappingSub> WrappingSub for Wrapping<T> where Wrapping<T>: Sub<Output = Wrapping<T>> {
|
||||||
where
|
|
||||||
Wrapping<T>: Sub<Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn wrapping_sub(&self, v: &Self) -> Self {
|
fn wrapping_sub(&self, v: &Self) -> Self {
|
||||||
Wrapping(self.0.wrapping_sub(&v.0))
|
Wrapping(self.0.wrapping_sub(&v.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: WrappingMul> WrappingMul for Wrapping<T>
|
impl<T: WrappingMul> WrappingMul for Wrapping<T> where Wrapping<T>: Mul<Output = Wrapping<T>> {
|
||||||
where
|
|
||||||
Wrapping<T>: Mul<Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn wrapping_mul(&self, v: &Self) -> Self {
|
fn wrapping_mul(&self, v: &Self) -> Self {
|
||||||
Wrapping(self.0.wrapping_mul(&v.0))
|
Wrapping(self.0.wrapping_mul(&v.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T: WrappingShl> WrappingShl for Wrapping<T>
|
|
||||||
where
|
|
||||||
Wrapping<T>: Shl<usize, Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn wrapping_shl(&self, rhs: u32) -> Self {
|
|
||||||
Wrapping(self.0.wrapping_shl(rhs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: WrappingShr> WrappingShr for Wrapping<T>
|
|
||||||
where
|
|
||||||
Wrapping<T>: Shr<usize, Output = Wrapping<T>>,
|
|
||||||
{
|
|
||||||
fn wrapping_shr(&self, rhs: u32) -> Self {
|
|
||||||
Wrapping(self.0.wrapping_shr(rhs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wrapping_traits() {
|
fn test_wrapping_traits() {
|
||||||
fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T {
|
fn wrapping_add<T: WrappingAdd>(a: T, b: T) -> T { a.wrapping_add(&b) }
|
||||||
a.wrapping_add(&b)
|
fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T { a.wrapping_sub(&b) }
|
||||||
}
|
fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T { a.wrapping_mul(&b) }
|
||||||
fn wrapping_sub<T: WrappingSub>(a: T, b: T) -> T {
|
|
||||||
a.wrapping_sub(&b)
|
|
||||||
}
|
|
||||||
fn wrapping_mul<T: WrappingMul>(a: T, b: T) -> T {
|
|
||||||
a.wrapping_mul(&b)
|
|
||||||
}
|
|
||||||
fn wrapping_shl<T: WrappingShl>(a: T, b: u32) -> T {
|
|
||||||
a.wrapping_shl(b)
|
|
||||||
}
|
|
||||||
fn wrapping_shr<T: WrappingShr>(a: T, b: u32) -> T {
|
|
||||||
a.wrapping_shr(b)
|
|
||||||
}
|
|
||||||
assert_eq!(wrapping_add(255, 1), 0u8);
|
assert_eq!(wrapping_add(255, 1), 0u8);
|
||||||
assert_eq!(wrapping_sub(0, 1), 255u8);
|
assert_eq!(wrapping_sub(0, 1), 255u8);
|
||||||
assert_eq!(wrapping_mul(255, 2), 254u8);
|
assert_eq!(wrapping_mul(255, 2), 254u8);
|
||||||
assert_eq!(wrapping_shl(255, 8), 255u8);
|
|
||||||
assert_eq!(wrapping_shr(255, 8), 255u8);
|
|
||||||
assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
|
assert_eq!(wrapping_add(255, 1), (Wrapping(255u8) + Wrapping(1u8)).0);
|
||||||
assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
|
assert_eq!(wrapping_sub(0, 1), (Wrapping(0u8) - Wrapping(1u8)).0);
|
||||||
assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
|
assert_eq!(wrapping_mul(255, 2), (Wrapping(255u8) * Wrapping(2u8)).0);
|
||||||
assert_eq!(wrapping_shl(255, 8), (Wrapping(255u8) << 8).0);
|
|
||||||
assert_eq!(wrapping_shr(255, 8), (Wrapping(255u8) >> 8).0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -258,15 +137,3 @@ fn wrapping_is_wrappingmul() {
|
||||||
fn require_wrappingmul<T: WrappingMul>(_: &T) {}
|
fn require_wrappingmul<T: WrappingMul>(_: &T) {}
|
||||||
require_wrappingmul(&Wrapping(42));
|
require_wrappingmul(&Wrapping(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrapping_is_wrappingshl() {
|
|
||||||
fn require_wrappingshl<T: WrappingShl>(_: &T) {}
|
|
||||||
require_wrappingshl(&Wrapping(42));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn wrapping_is_wrappingshr() {
|
|
||||||
fn require_wrappingshr<T: WrappingShr>(_: &T) {}
|
|
||||||
require_wrappingshr(&Wrapping(42));
|
|
||||||
}
|
|
||||||
|
|
61
src/pow.rs
61
src/pow.rs
|
@ -1,6 +1,6 @@
|
||||||
use core::num::Wrapping;
|
|
||||||
use core::ops::Mul;
|
use core::ops::Mul;
|
||||||
use {CheckedMul, One};
|
use core::num::Wrapping;
|
||||||
|
use {One, CheckedMul};
|
||||||
|
|
||||||
/// Binary operator for raising a value to a power.
|
/// Binary operator for raising a value to a power.
|
||||||
pub trait Pow<RHS> {
|
pub trait Pow<RHS> {
|
||||||
|
@ -152,30 +152,27 @@ pow_impl!(Wrapping<isize>);
|
||||||
// pow_impl!(usize, u64);
|
// pow_impl!(usize, u64);
|
||||||
// pow_impl!(isize, u64);
|
// pow_impl!(isize, u64);
|
||||||
|
|
||||||
#[cfg(any(feature = "std", feature = "libm"))]
|
#[cfg(feature = "std")]
|
||||||
mod float_impls {
|
mod float_impls {
|
||||||
use super::Pow;
|
use super::Pow;
|
||||||
use Float;
|
|
||||||
|
|
||||||
pow_impl!(f32, i8, i32, <f32 as Float>::powi);
|
pow_impl!(f32, i8, i32, f32::powi);
|
||||||
pow_impl!(f32, u8, i32, <f32 as Float>::powi);
|
pow_impl!(f32, u8, i32, f32::powi);
|
||||||
pow_impl!(f32, i16, i32, <f32 as Float>::powi);
|
pow_impl!(f32, i16, i32, f32::powi);
|
||||||
pow_impl!(f32, u16, i32, <f32 as Float>::powi);
|
pow_impl!(f32, u16, i32, f32::powi);
|
||||||
pow_impl!(f32, i32, i32, <f32 as Float>::powi);
|
pow_impl!(f32, i32, i32, f32::powi);
|
||||||
pow_impl!(f64, i8, i32, <f64 as Float>::powi);
|
pow_impl!(f64, i8, i32, f64::powi);
|
||||||
pow_impl!(f64, u8, i32, <f64 as Float>::powi);
|
pow_impl!(f64, u8, i32, f64::powi);
|
||||||
pow_impl!(f64, i16, i32, <f64 as Float>::powi);
|
pow_impl!(f64, i16, i32, f64::powi);
|
||||||
pow_impl!(f64, u16, i32, <f64 as Float>::powi);
|
pow_impl!(f64, u16, i32, f64::powi);
|
||||||
pow_impl!(f64, i32, i32, <f64 as Float>::powi);
|
pow_impl!(f64, i32, i32, f64::powi);
|
||||||
pow_impl!(f32, f32, f32, <f32 as Float>::powf);
|
pow_impl!(f32, f32, f32, f32::powf);
|
||||||
pow_impl!(f64, f32, f64, <f64 as Float>::powf);
|
pow_impl!(f64, f32, f64, f64::powf);
|
||||||
pow_impl!(f64, f64, f64, <f64 as Float>::powf);
|
pow_impl!(f64, f64, f64, f64::powf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raises a value to the power of exp, using exponentiation by squaring.
|
/// Raises a value to the power of exp, using exponentiation by squaring.
|
||||||
///
|
///
|
||||||
/// Note that `0⁰` (`pow(0, 0)`) returns `1`. Mathematically this is undefined.
|
|
||||||
///
|
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
@ -183,21 +180,16 @@ mod float_impls {
|
||||||
///
|
///
|
||||||
/// assert_eq!(pow(2i8, 4), 16);
|
/// assert_eq!(pow(2i8, 4), 16);
|
||||||
/// assert_eq!(pow(6u8, 3), 216);
|
/// assert_eq!(pow(6u8, 3), 216);
|
||||||
/// assert_eq!(pow(0u8, 0), 1); // Be aware if this case affects you
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
|
pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) -> T {
|
||||||
if exp == 0 {
|
if exp == 0 { return T::one() }
|
||||||
return T::one();
|
|
||||||
}
|
|
||||||
|
|
||||||
while exp & 1 == 0 {
|
while exp & 1 == 0 {
|
||||||
base = base.clone() * base;
|
base = base.clone() * base;
|
||||||
exp >>= 1;
|
exp >>= 1;
|
||||||
}
|
}
|
||||||
if exp == 1 {
|
if exp == 1 { return base }
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut acc = base.clone();
|
let mut acc = base.clone();
|
||||||
while exp > 1 {
|
while exp > 1 {
|
||||||
|
@ -212,8 +204,6 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
|
||||||
|
|
||||||
/// Raises a value to the power of exp, returning `None` if an overflow occurred.
|
/// Raises a value to the power of exp, returning `None` if an overflow occurred.
|
||||||
///
|
///
|
||||||
/// Note that `0⁰` (`checked_pow(0, 0)`) returns `Some(1)`. Mathematically this is undefined.
|
|
||||||
///
|
|
||||||
/// Otherwise same as the `pow` function.
|
/// Otherwise same as the `pow` function.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
|
@ -224,31 +214,22 @@ pub fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: usize) ->
|
||||||
/// assert_eq!(checked_pow(2i8, 4), Some(16));
|
/// assert_eq!(checked_pow(2i8, 4), Some(16));
|
||||||
/// assert_eq!(checked_pow(7i8, 8), None);
|
/// assert_eq!(checked_pow(7i8, 8), None);
|
||||||
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
|
/// assert_eq!(checked_pow(7u32, 8), Some(5_764_801));
|
||||||
/// assert_eq!(checked_pow(0u32, 0), Some(1)); // Be aware if this case affect you
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
|
pub fn checked_pow<T: Clone + One + CheckedMul>(mut base: T, mut exp: usize) -> Option<T> {
|
||||||
if exp == 0 {
|
if exp == 0 { return Some(T::one()) }
|
||||||
return Some(T::one());
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! optry {
|
macro_rules! optry {
|
||||||
( $ expr : expr ) => {
|
( $ expr : expr ) => {
|
||||||
if let Some(val) = $expr {
|
if let Some(val) = $expr { val } else { return None }
|
||||||
val
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while exp & 1 == 0 {
|
while exp & 1 == 0 {
|
||||||
base = optry!(base.checked_mul(&base));
|
base = optry!(base.checked_mul(&base));
|
||||||
exp >>= 1;
|
exp >>= 1;
|
||||||
}
|
}
|
||||||
if exp == 1 {
|
if exp == 1 { return Some(base) }
|
||||||
return Some(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut acc = base.clone();
|
let mut acc = base.clone();
|
||||||
while exp > 1 {
|
while exp > 1 {
|
||||||
|
|
16
src/real.rs
16
src/real.rs
|
@ -1,8 +1,6 @@
|
||||||
#![cfg(any(feature = "std", feature = "libm"))]
|
use std::ops::Neg;
|
||||||
|
|
||||||
use core::ops::Neg;
|
use {Num, NumCast, Float};
|
||||||
|
|
||||||
use {Float, Num, NumCast};
|
|
||||||
|
|
||||||
// NOTE: These doctests have the same issue as those in src/float.rs.
|
// NOTE: These doctests have the same issue as those in src/float.rs.
|
||||||
// They're testing the inherent methods directly, and not those of `Real`.
|
// They're testing the inherent methods directly, and not those of `Real`.
|
||||||
|
@ -13,8 +11,14 @@ use {Float, Num, NumCast};
|
||||||
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
|
/// See [this Wikipedia article](https://en.wikipedia.org/wiki/Real_data_type)
|
||||||
/// for a list of data types that could meaningfully implement this trait.
|
/// for a list of data types that could meaningfully implement this trait.
|
||||||
///
|
///
|
||||||
/// This trait is only available with the `std` feature, or with the `libm` feature otherwise.
|
/// This trait is only available with the `std` feature.
|
||||||
pub trait Real: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
|
pub trait Real
|
||||||
|
: Num
|
||||||
|
+ Copy
|
||||||
|
+ NumCast
|
||||||
|
+ PartialOrd
|
||||||
|
+ Neg<Output = Self>
|
||||||
|
{
|
||||||
/// Returns the smallest finite value that this type can represent.
|
/// Returns the smallest finite value that this type can represent.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
35
src/sign.rs
35
src/sign.rs
|
@ -1,8 +1,8 @@
|
||||||
use core::num::Wrapping;
|
|
||||||
use core::ops::Neg;
|
use core::ops::Neg;
|
||||||
|
use core::num::Wrapping;
|
||||||
|
|
||||||
use float::FloatCore;
|
|
||||||
use Num;
|
use Num;
|
||||||
|
use float::FloatCore;
|
||||||
|
|
||||||
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
/// Useful functions for signed numbers (i.e. numbers that can be negative).
|
||||||
pub trait Signed: Sized + Num + Neg<Output = Self> {
|
pub trait Signed: Sized + Num + Neg<Output = Self> {
|
||||||
|
@ -77,9 +77,7 @@ signed_impl!(isize i8 i16 i32 i64);
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
signed_impl!(i128);
|
signed_impl!(i128);
|
||||||
|
|
||||||
impl<T: Signed> Signed for Wrapping<T>
|
impl<T: Signed> Signed for Wrapping<T> where Wrapping<T>: Num + Neg<Output=Wrapping<T>>
|
||||||
where
|
|
||||||
Wrapping<T>: Num + Neg<Output = Wrapping<T>>,
|
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs(&self) -> Self {
|
fn abs(&self) -> Self {
|
||||||
|
@ -97,14 +95,10 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_positive(&self) -> bool {
|
fn is_positive(&self) -> bool { self.0.is_positive() }
|
||||||
self.0.is_positive()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_negative(&self) -> bool {
|
fn is_negative(&self) -> bool { self.0.is_negative() }
|
||||||
self.0.is_negative()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! signed_float_impl {
|
macro_rules! signed_float_impl {
|
||||||
|
@ -121,11 +115,7 @@ macro_rules! signed_float_impl {
|
||||||
/// and `other` is returned.
|
/// and `other` is returned.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn abs_sub(&self, other: &$t) -> $t {
|
fn abs_sub(&self, other: &$t) -> $t {
|
||||||
if *self <= *other {
|
if *self <= *other { 0. } else { *self - *other }
|
||||||
0.
|
|
||||||
} else {
|
|
||||||
*self - *other
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Returns
|
/// # Returns
|
||||||
|
@ -140,17 +130,13 @@ macro_rules! signed_float_impl {
|
||||||
|
|
||||||
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
/// Returns `true` if the number is positive, including `+0.0` and `INFINITY`
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_positive(&self) -> bool {
|
fn is_positive(&self) -> bool { FloatCore::is_sign_positive(*self) }
|
||||||
FloatCore::is_sign_positive(*self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
|
/// Returns `true` if the number is negative, including `-0.0` and `NEG_INFINITY`
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_negative(&self) -> bool {
|
fn is_negative(&self) -> bool { FloatCore::is_sign_negative(*self) }
|
||||||
FloatCore::is_sign_negative(*self)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signed_float_impl!(f32);
|
signed_float_impl!(f32);
|
||||||
|
@ -188,10 +174,7 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
||||||
/// * `0` if the number is zero
|
/// * `0` if the number is zero
|
||||||
/// * `1` if the number is positive
|
/// * `1` if the number is positive
|
||||||
/// * `-1` if the number is negative
|
/// * `-1` if the number is negative
|
||||||
#[inline(always)]
|
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
|
||||||
pub fn signum<T: Signed>(value: T) -> T {
|
|
||||||
value.signum()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A trait for values which cannot be negative
|
/// A trait for values which cannot be negative
|
||||||
pub trait Unsigned: Num {}
|
pub trait Unsigned: Num {}
|
||||||
|
|
|
@ -11,11 +11,11 @@ extern crate num_traits;
|
||||||
use num_traits::cast::*;
|
use num_traits::cast::*;
|
||||||
use num_traits::Bounded;
|
use num_traits::Bounded;
|
||||||
|
|
||||||
|
use core::{i8, i16, i32, i64, isize};
|
||||||
|
use core::{u8, u16, u32, u64, usize};
|
||||||
use core::{f32, f64};
|
use core::{f32, f64};
|
||||||
#[cfg(has_i128)]
|
#[cfg(has_i128)]
|
||||||
use core::{i128, u128};
|
use core::{i128, u128};
|
||||||
use core::{i16, i32, i64, i8, isize};
|
|
||||||
use core::{u16, u32, u64, u8, usize};
|
|
||||||
|
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
|
|
Loading…
Reference in New Issue