@@ -220,10 +220,23 @@ impl<T: Clone + Float> Complex<T> {
220220 /// The branch satisfies `-π/2 ≤ arg(sqrt(z)) ≤ π/2`.
221221 #[ inline]
222222 pub fn sqrt ( & self ) -> Self {
223- // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2)
224- let two = T :: one ( ) + T :: one ( ) ;
225- let ( r, theta) = self . to_polar ( ) ;
226- Self :: from_polar ( & ( r. sqrt ( ) ) , & ( theta / two) )
223+ if self . im . is_zero ( ) {
224+ if self . re . is_sign_positive ( ) {
225+ // simple positive real √r, and copy `im` for its sign
226+ Self :: new ( self . re . sqrt ( ) , self . im )
227+ } else if self . im . is_sign_positive ( ) {
228+ // √(r e^(iπ)) = √r e^(iπ/2) = i√r
229+ Self :: new ( T :: zero ( ) , self . re . abs ( ) . sqrt ( ) )
230+ } else {
231+ // √(r e^(-iπ)) = √r e^(-iπ/2) = -i√r
232+ Self :: new ( T :: zero ( ) , -self . re . abs ( ) . sqrt ( ) )
233+ }
234+ } else {
235+ // formula: sqrt(r e^(it)) = sqrt(r) e^(it/2)
236+ let two = T :: one ( ) + T :: one ( ) ;
237+ let ( r, theta) = self . to_polar ( ) ;
238+ Self :: from_polar ( & ( r. sqrt ( ) ) , & ( theta / two) )
239+ }
227240 }
228241
229242 /// Raises `self` to a floating point power.
@@ -1690,6 +1703,18 @@ mod test {
16901703 }
16911704 }
16921705
1706+ #[ test]
1707+ fn test_sqrt_real ( ) {
1708+ for n in ( 0 ..100 ) . map ( f64:: from) {
1709+ // √(n² + 0i) = n + 0i
1710+ assert_eq ! ( Complex64 :: new( n * n, 0.0 ) . sqrt( ) , Complex64 :: new( n, 0.0 ) ) ;
1711+ // √(-n² + 0i) = 0 + ni
1712+ assert_eq ! ( Complex64 :: new( -n * n, 0.0 ) . sqrt( ) , Complex64 :: new( 0.0 , n) ) ;
1713+ // √(-n² - 0i) = 0 - ni
1714+ assert_eq ! ( Complex64 :: new( -n * n, -0.0 ) . sqrt( ) , Complex64 :: new( 0.0 , -n) ) ;
1715+ }
1716+ }
1717+
16931718 #[ test]
16941719 fn test_sin ( ) {
16951720 assert ! ( close( _0_0i. sin( ) , _0_0i) ) ;
0 commit comments