@@ -1862,6 +1862,35 @@ pub trait Float: Num + Copy + NumCast + PartialOrd + Neg<Output = Self> {
1862
1862
/// assert!(abs_difference < 1e-10);
1863
1863
/// ```
1864
1864
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
+ }
1865
1894
}
1866
1895
1867
1896
#[ cfg( feature = "std" ) ]
@@ -1939,6 +1968,12 @@ macro_rules! float_impl_std {
1939
1968
Self :: acosh( self ) -> Self ;
1940
1969
Self :: atanh( self ) -> Self ;
1941
1970
}
1971
+
1972
+ #[ cfg( has_copysign) ]
1973
+ #[ inline]
1974
+ fn copysign( self , sign: Self ) -> Self {
1975
+ Self :: copysign( self , sign)
1976
+ }
1942
1977
}
1943
1978
} ;
1944
1979
}
@@ -2070,6 +2105,7 @@ impl Float for f32 {
2070
2105
libm:: atanhf as atanh( self ) -> Self ;
2071
2106
libm:: fmaxf as max( self , other: Self ) -> Self ;
2072
2107
libm:: fminf as min( self , other: Self ) -> Self ;
2108
+ libm:: copysignf as copysign( self , other: Self ) -> Self ;
2073
2109
}
2074
2110
}
2075
2111
@@ -2117,6 +2153,7 @@ impl Float for f64 {
2117
2153
libm:: atanh as atanh( self ) -> Self ;
2118
2154
libm:: fmax as max( self , other: Self ) -> Self ;
2119
2155
libm:: fmin as min( self , other: Self ) -> Self ;
2156
+ libm:: copysign as copysign( self , sign: Self ) -> Self ;
2120
2157
}
2121
2158
}
2122
2159
@@ -2265,4 +2302,48 @@ mod tests {
2265
2302
check :: < f32 > ( 1e-6 ) ;
2266
2303
check :: < f64 > ( 1e-12 ) ;
2267
2304
}
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
+ }
2268
2349
}
0 commit comments