@@ -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
}
@@ -2048,6 +2083,7 @@ impl Float for f32 {
2048
2083
libm:: atanhf as atanh( self ) -> Self ;
2049
2084
libm:: fmaxf as max( self , other: Self ) -> Self ;
2050
2085
libm:: fminf as min( self , other: Self ) -> Self ;
2086
+ libm:: copysignf as copysign( self , other: Self ) -> Self ;
2051
2087
}
2052
2088
}
2053
2089
@@ -2095,6 +2131,8 @@ impl Float for f64 {
2095
2131
libm:: atanh as atanh( self ) -> Self ;
2096
2132
libm:: fmax as max( self , other: Self ) -> Self ;
2097
2133
libm:: fmin as min( self , other: Self ) -> Self ;
2134
+ libm:: copysign as copysign( self , sign: Self ) -> Self ;
2135
+ libm:: copysignf as copysignf( self , sign: Self ) -> Self ;
2098
2136
}
2099
2137
}
2100
2138
@@ -2243,4 +2281,44 @@ mod tests {
2243
2281
check :: < f32 > ( 1e-6 ) ;
2244
2282
check :: < f64 > ( 1e-12 ) ;
2245
2283
}
2284
+
2285
+ #[ test]
2286
+ fn copysign ( ) {
2287
+ use float:: Float ;
2288
+ test_copysign_generic ( 2.0_f32 , -2.0_f32 , f32:: nan ( ) ) ;
2289
+ test_copysign_generic ( 2.0_f64 , -2.0_f64 , f64:: nan ( ) ) ;
2290
+ test_copysignf ( 2.0_f32 , -2.0_f32 , f32:: nan ( ) ) ;
2291
+ }
2292
+
2293
+ fn test_copysignf ( p : f32 , n : f32 , nan : f32 ) {
2294
+ use core:: ops:: Neg ;
2295
+
2296
+ assert ! ( p. is_sign_positive( ) ) ;
2297
+ assert ! ( n. is_sign_negative( ) ) ;
2298
+ assert ! ( nan. is_nan( ) ) ;
2299
+
2300
+ assert_eq ! ( p, p. copysign( p) ) ;
2301
+ assert_eq ! ( p. neg( ) , p. copysign( n) ) ;
2302
+
2303
+ assert_eq ! ( n, n. copysign( n) ) ;
2304
+ assert_eq ! ( n. neg( ) , n. copysign( p) ) ;
2305
+
2306
+ assert ! ( nan. copysign( p) . is_sign_positive( ) ) ;
2307
+ assert ! ( nan. copysign( n) . is_sign_negative( ) ) ;
2308
+ }
2309
+
2310
+ fn test_copysign_generic < F : :: float:: Float + core:: fmt:: Debug > ( p : F , n : F , nan : F ) {
2311
+ assert ! ( p. is_sign_positive( ) ) ;
2312
+ assert ! ( n. is_sign_negative( ) ) ;
2313
+ assert ! ( nan. is_nan( ) ) ;
2314
+
2315
+ assert_eq ! ( p, p. copysign( p) ) ;
2316
+ assert_eq ! ( p. neg( ) , p. copysign( n) ) ;
2317
+
2318
+ assert_eq ! ( n, n. copysign( n) ) ;
2319
+ assert_eq ! ( n. neg( ) , n. copysign( p) ) ;
2320
+
2321
+ assert ! ( nan. copysign( p) . is_sign_positive( ) ) ;
2322
+ assert ! ( nan. copysign( n) . is_sign_negative( ) ) ;
2323
+ }
2246
2324
}
0 commit comments