@@ -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,12 @@ 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
+ #[ inline]
1952
+ fn copysign( self , sign: Self ) -> Self {
1953
+ Self :: copysign( self , sign)
1954
+ }
1920
1955
}
1921
1956
} ;
1922
1957
}
@@ -2096,6 +2131,11 @@ impl Float for f64 {
2096
2131
libm:: fmax as max( self , other: Self ) -> Self ;
2097
2132
libm:: fmin as min( self , other: Self ) -> Self ;
2098
2133
}
2134
+
2135
+ #[ cfg( has_copysign) ]
2136
+ forward ! {
2137
+ libm:: copysign as copysign( self , sign: Self ) -> Self ;
2138
+ }
2099
2139
}
2100
2140
2101
2141
macro_rules! float_const_impl {
@@ -2243,4 +2283,28 @@ mod tests {
2243
2283
check :: < f32 > ( 1e-6 ) ;
2244
2284
check :: < f64 > ( 1e-12 ) ;
2245
2285
}
2286
+
2287
+ #[ cfg( all( any( feature = "std" , feature = "libm" ) , has_copysign) ) ]
2288
+ #[ test]
2289
+ fn copysign ( ) {
2290
+ use float:: Float ;
2291
+ test_copysign_generic ( 2.0_f32 , -2.0_f32 , f32:: nan ( ) ) ;
2292
+ test_copysign_generic ( 2.0_f64 , -2.0_f64 , f64:: nan ( ) ) ;
2293
+ }
2294
+
2295
+ #[ cfg( all( any( feature = "std" , feature = "libm" ) , has_copysign) ) ]
2296
+ fn test_copysign_generic < F : :: float:: Float + core:: fmt:: Debug > ( p : F , n : F , nan : F ) {
2297
+ assert ! ( p. is_sign_positive( ) ) ;
2298
+ assert ! ( n. is_sign_negative( ) ) ;
2299
+ assert ! ( nan. is_nan( ) ) ;
2300
+
2301
+ assert_eq ! ( p, p. copysign( p) ) ;
2302
+ assert_eq ! ( p. neg( ) , p. copysign( n) ) ;
2303
+
2304
+ assert_eq ! ( n, n. copysign( n) ) ;
2305
+ assert_eq ! ( n. neg( ) , n. copysign( p) ) ;
2306
+
2307
+ assert ! ( nan. copysign( p) . is_sign_positive( ) ) ;
2308
+ assert ! ( nan. copysign( n) . is_sign_negative( ) ) ;
2309
+ }
2246
2310
}
0 commit comments