@@ -1840,6 +1840,35 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
1840
1840
/// assert!(abs_difference < 1e-10);
1841
1841
/// ```
1842
1842
fn integer_decode ( self ) -> ( u64 , i16 , i8 ) ;
1843
+
1844
+ /// Returns a number composed of the magnitude of `self` and the sign of
1845
+ /// `sign`.
1846
+ ///
1847
+ /// Equal to `self` if the sign of `self` and `sign` are the same, otherwise
1848
+ /// equal to `-self`. If `self` is a `NAN`, then a `NAN` with the sign of
1849
+ /// `sign` is returned.
1850
+ ///
1851
+ /// # Examples
1852
+ ///
1853
+ /// ```
1854
+ /// use num_traits::Float;
1855
+ ///
1856
+ /// let f = 3.5_f32;
1857
+ ///
1858
+ /// assert_eq!(f.copysign(0.42), 3.5_f32);
1859
+ /// assert_eq!(f.copysign(-0.42), -3.5_f32);
1860
+ /// assert_eq!((-f).copysign(0.42), 3.5_f32);
1861
+ /// assert_eq!((-f).copysign(-0.42), -3.5_f32);
1862
+ ///
1863
+ /// assert!(f32::nan().copysign(1.0).is_nan());
1864
+ /// ```
1865
+ fn copysign ( self , sign : Self ) -> Self {
1866
+ if self . is_sign_negative ( ) == sign. is_sign_negative ( ) {
1867
+ self
1868
+ } else {
1869
+ self . neg ( )
1870
+ }
1871
+ }
1843
1872
}
1844
1873
1845
1874
#[ cfg( feature = "std" ) ]
@@ -1917,6 +1946,11 @@ macro_rules! float_impl_std {
1917
1946
Self :: acosh( self ) -> Self ;
1918
1947
Self :: atanh( self ) -> Self ;
1919
1948
}
1949
+
1950
+ #[ cfg( has_copysign) ]
1951
+ forward! {
1952
+ Self :: copysign( self , sign: Self ) -> Self ;
1953
+ }
1920
1954
}
1921
1955
} ;
1922
1956
}
@@ -2095,6 +2129,7 @@ impl Float for f64 {
2095
2129
libm:: atanh as atanh( self ) -> Self ;
2096
2130
libm:: fmax as max( self , other: Self ) -> Self ;
2097
2131
libm:: fmin as min( self , other: Self ) -> Self ;
2132
+ libm:: copysign as copysign( self , sign: Self ) -> Self ;
2098
2133
}
2099
2134
}
2100
2135
@@ -2243,4 +2278,28 @@ mod tests {
2243
2278
check :: < f32 > ( 1e-6 ) ;
2244
2279
check :: < f64 > ( 1e-12 ) ;
2245
2280
}
2281
+
2282
+ #[ cfg( all( any( feature = "std" , feature = "libm" ) , has_copysign) ) ]
2283
+ #[ test]
2284
+ fn copysign ( ) {
2285
+ use float:: Float ;
2286
+ test_copysign_generic ( 2.0_f32 , -2.0_f32 , f32:: nan ( ) ) ;
2287
+ test_copysign_generic ( 2.0_f64 , -2.0_f64 , f64:: nan ( ) ) ;
2288
+ }
2289
+
2290
+ #[ cfg( all( any( feature = "std" , feature = "libm" ) , has_copysign) ) ]
2291
+ fn test_copysign_generic < F : :: float:: Float + core:: fmt:: Debug > ( p : F , n : F , nan : F ) {
2292
+ assert ! ( p. is_sign_positive( ) ) ;
2293
+ assert ! ( n. is_sign_negative( ) ) ;
2294
+ assert ! ( nan. is_nan( ) ) ;
2295
+
2296
+ assert_eq ! ( p, p. copysign( p) ) ;
2297
+ assert_eq ! ( p. neg( ) , p. copysign( n) ) ;
2298
+
2299
+ assert_eq ! ( n, n. copysign( n) ) ;
2300
+ assert_eq ! ( n. neg( ) , n. copysign( p) ) ;
2301
+
2302
+ assert ! ( nan. copysign( p) . is_sign_positive( ) ) ;
2303
+ assert ! ( nan. copysign( n) . is_sign_negative( ) ) ;
2304
+ }
2246
2305
}
0 commit comments