Skip to content

Commit ce9a7df

Browse files
XAMPPRockyctrlcctrlv
authored andcommitted
Add copysign (upstream PR rust-num#207)
Signed-off-by: Fredrick Brennan <[email protected]>
1 parent 96a89e6 commit ce9a7df

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ libm = { version = "0.2.0", optional = true }
2323
default = ["std"]
2424
std = []
2525
i128 = []
26+
copysign = []
2627

2728
[build-dependencies]
2829
autocfg = "1"

build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ fn main() {
1111
autocfg::emit("has_i128");
1212
}
1313

14+
if env::var_os("CARGO_FEATURE_COPYSIGN").is_some() || ac.probe_expression("f32::copysign") {
15+
autocfg::emit("has_copysign");
16+
}
17+
1418
ac.emit_expression_cfg(
1519
"unsafe { 1f64.to_int_unchecked::<i32>() }",
1620
"has_to_int_unchecked",

src/float.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,35 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
18621862
/// assert!(abs_difference < 1e-10);
18631863
/// ```
18641864
fn integer_decode(self) -> (u64, i16, i8);
1865+
1866+
/// Returns a number composed of the magnitude of `self` and the sign of
1867+
/// `sign`.
1868+
///
1869+
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
1870+
/// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
1871+
/// `sign` is returned.
1872+
///
1873+
/// # Examples
1874+
///
1875+
/// ```
1876+
/// use num_traits::Float;
1877+
///
1878+
/// let f = 3.5_f32;
1879+
///
1880+
/// assert_eq!(f.copysign(0.42), 3.5_f32);
1881+
/// assert_eq!(f.copysign(-0.42), -3.5_f32);
1882+
/// assert_eq!((-f).copysign(0.42), 3.5_f32);
1883+
/// assert_eq!((-f).copysign(-0.42), -3.5_f32);
1884+
///
1885+
/// assert!(f32::nan().copysign(1.0).is_nan());
1886+
/// ```
1887+
fn copysign(self, sign: Self) -> Self {
1888+
if self.is_sign_negative() == sign.is_sign_negative() {
1889+
self
1890+
} else {
1891+
self.neg()
1892+
}
1893+
}
18651894
}
18661895

18671896
#[cfg(feature = "std")]
@@ -1939,6 +1968,12 @@ macro_rules! float_impl_std {
19391968
Self::acosh(self) -> Self;
19401969
Self::atanh(self) -> Self;
19411970
}
1971+
1972+
#[cfg(has_copysign)]
1973+
#[inline]
1974+
fn copysign(self, sign: Self) -> Self {
1975+
Self::copysign(self, sign)
1976+
}
19421977
}
19431978
};
19441979
}
@@ -2070,6 +2105,7 @@ impl Float for f32 {
20702105
libm::atanhf as atanh(self) -> Self;
20712106
libm::fmaxf as max(self, other: Self) -> Self;
20722107
libm::fminf as min(self, other: Self) -> Self;
2108+
libm::copysignf as copysign(self, other: Self) -> Self;
20732109
}
20742110
}
20752111

@@ -2117,6 +2153,7 @@ impl Float for f64 {
21172153
libm::atanh as atanh(self) -> Self;
21182154
libm::fmax as max(self, other: Self) -> Self;
21192155
libm::fmin as min(self, other: Self) -> Self;
2156+
libm::copysign as copysign(self, sign: Self) -> Self;
21202157
}
21212158
}
21222159

@@ -2265,4 +2302,48 @@ mod tests {
22652302
check::<f32>(1e-6);
22662303
check::<f64>(1e-12);
22672304
}
2305+
2306+
#[test]
2307+
#[cfg(any(feature = "std", feature = "libm"))]
2308+
fn copysign() {
2309+
use float::Float;
2310+
test_copysign_generic(2.0_f32, -2.0_f32, f32::nan());
2311+
test_copysign_generic(2.0_f64, -2.0_f64, f64::nan());
2312+
test_copysignf(2.0_f32, -2.0_f32, f32::nan());
2313+
}
2314+
2315+
#[cfg(any(feature = "std", feature = "libm"))]
2316+
fn test_copysignf(p: f32, n: f32, nan: f32) {
2317+
use float::Float;
2318+
use core::ops::Neg;
2319+
2320+
assert!(p.is_sign_positive());
2321+
assert!(n.is_sign_negative());
2322+
assert!(nan.is_nan());
2323+
2324+
assert_eq!(p, p.copysign(p));
2325+
assert_eq!(p.neg(), p.copysign(n));
2326+
2327+
assert_eq!(n, n.copysign(n));
2328+
assert_eq!(n.neg(), n.copysign(p));
2329+
2330+
assert!(nan.copysign(p).is_sign_positive());
2331+
assert!(nan.copysign(n).is_sign_negative());
2332+
}
2333+
2334+
#[cfg(any(feature = "std", feature = "libm"))]
2335+
fn test_copysign_generic<F: ::float::Float + core::fmt::Debug>(p: F, n: F, nan: F) {
2336+
assert!(p.is_sign_positive());
2337+
assert!(n.is_sign_negative());
2338+
assert!(nan.is_nan());
2339+
2340+
assert_eq!(p, p.copysign(p));
2341+
assert_eq!(p.neg(), p.copysign(n));
2342+
2343+
assert_eq!(n, n.copysign(n));
2344+
assert_eq!(n.neg(), n.copysign(p));
2345+
2346+
assert!(nan.copysign(p).is_sign_positive());
2347+
assert!(nan.copysign(n).is_sign_negative());
2348+
}
22682349
}

0 commit comments

Comments
 (0)