@@ -120,7 +120,8 @@ impl<T: Clone + Float> Complex<T> {
120
120
#[ inline]
121
121
pub fn exp ( & self ) -> Complex < T > {
122
122
// formula: e^(a + bi) = e^a (cos(b) + i*sin(b))
123
- Complex :: new ( self . im . cos ( ) , self . im . sin ( ) ) . scale ( self . re . exp ( ) )
123
+ // = from_polar(e^a, b)
124
+ Complex :: from_polar ( & self . re . exp ( ) , & self . im )
124
125
}
125
126
126
127
/// Computes the principal value of natural logarithm of `self`.
@@ -133,7 +134,8 @@ impl<T: Clone + Float> Complex<T> {
133
134
#[ inline]
134
135
pub fn ln ( & self ) -> Complex < T > {
135
136
// formula: ln(z) = ln|z| + i*arg(z)
136
- Complex :: new ( self . norm ( ) . ln ( ) , self . arg ( ) )
137
+ let ( r, theta) = self . to_polar ( ) ;
138
+ Complex :: new ( r. ln ( ) , theta)
137
139
}
138
140
139
141
/// Computes the principal value of the square root of `self`.
@@ -150,6 +152,53 @@ impl<T: Clone + Float> Complex<T> {
150
152
let ( r, theta) = self . to_polar ( ) ;
151
153
Complex :: from_polar ( & ( r. sqrt ( ) ) , & ( theta/two) )
152
154
}
155
+
156
+ /// Raises `self` to a floating point power.
157
+ #[ inline]
158
+ pub fn powf ( & self , exp : T ) -> Complex < T > {
159
+ // formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y)
160
+ // = from_polar(ρ^y, θ y)
161
+ let ( r, theta) = self . to_polar ( ) ;
162
+ Complex :: from_polar ( & r. powf ( exp) , & ( theta* exp) )
163
+ }
164
+
165
+ /// Returns the logarithm of `self` with respect to an arbitrary base.
166
+ #[ inline]
167
+ pub fn log ( & self , base : T ) -> Complex < T > {
168
+ // formula: log_y(x) = log_y(ρ e^(i θ))
169
+ // = log_y(ρ) + log_y(e^(i θ)) = log_y(ρ) + ln(e^(i θ)) / ln(y)
170
+ // = log_y(ρ) + i θ / ln(y)
171
+ let ( r, theta) = self . to_polar ( ) ;
172
+ Complex :: new ( r. log ( base) , theta / base. ln ( ) )
173
+ }
174
+
175
+ /// Raises `self` to a complex power.
176
+ #[ inline]
177
+ pub fn powc ( & self , exp : Complex < T > ) -> Complex < T > {
178
+ // formula: x^y = (a + i b)^(c + i d)
179
+ // = (ρ e^(i θ))^c (ρ e^(i θ))^(i d)
180
+ // where ρ=|x| and θ=arg(x)
181
+ // = ρ^c e^(−d θ) e^(i c θ) ρ^(i d)
182
+ // = p^c e^(−d θ) (cos(c θ)
183
+ // + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ)))
184
+ // = p^c e^(−d θ) (
185
+ // cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ))
186
+ // + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ))))
187
+ // = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ)))
188
+ // = from_polar(p^c e^(−d θ), c θ + d ln(ρ))
189
+ let ( r, theta) = self . to_polar ( ) ;
190
+ Complex :: from_polar (
191
+ & ( r. powf ( exp. re ) * ( -exp. im * theta) . exp ( ) ) ,
192
+ & ( exp. re * theta + exp. im * r. ln ( ) ) )
193
+ }
194
+
195
+ /// Raises a floating point number to the complex power `self`.
196
+ #[ inline]
197
+ pub fn expf ( & self , base : T ) -> Complex < T > {
198
+ // formula: x^(a+bi) = x^a x^bi = x^a e^(b ln(x) i)
199
+ // = from_polar(x^a, b ln(x))
200
+ Complex :: from_polar ( & base. powf ( self . re ) , & ( self . im * base. ln ( ) ) )
201
+ }
153
202
154
203
/// Computes the sine of `self`.
155
204
#[ inline]
@@ -716,8 +765,12 @@ mod test {
716
765
}
717
766
718
767
fn close ( a : Complex64 , b : Complex64 ) -> bool {
768
+ close_to_tol ( a, b, 1e-10 )
769
+ }
770
+
771
+ fn close_to_tol ( a : Complex64 , b : Complex64 , tol : f64 ) -> bool {
719
772
// returns true if a and b are reasonably close
720
- ( a == b) || ( a-b) . norm ( ) < 1e-10
773
+ ( a == b) || ( a-b) . norm ( ) < tol
721
774
}
722
775
723
776
#[ test]
@@ -748,6 +801,49 @@ mod test {
748
801
assert ! ( -f64 :: consts:: PI <= c. ln( ) . arg( ) && c. ln( ) . arg( ) <= f64 :: consts:: PI ) ;
749
802
}
750
803
}
804
+
805
+ #[ test]
806
+ fn test_powc ( )
807
+ {
808
+ let a = Complex :: new ( 2.0 , -3.0 ) ;
809
+ let b = Complex :: new ( 3.0 , 0.0 ) ;
810
+ assert ! ( close( a. powc( b) , a. powf( b. re) ) ) ;
811
+ assert ! ( close( b. powc( a) , a. expf( b. re) ) ) ;
812
+ let c = Complex :: new ( 1.0 / 3.0 , 0.1 ) ;
813
+ assert ! ( close_to_tol( a. powc( c) , Complex :: new( 1.65826 , -0.33502 ) , 1e-5 ) ) ;
814
+ }
815
+
816
+ #[ test]
817
+ fn test_powf ( )
818
+ {
819
+ let c = Complex :: new ( 2.0 , -1.0 ) ;
820
+ let r = c. powf ( 3.5 ) ;
821
+ assert ! ( close_to_tol( r, Complex :: new( -0.8684746 , -16.695934 ) , 1e-5 ) ) ;
822
+ }
823
+
824
+ #[ test]
825
+ fn test_log ( )
826
+ {
827
+ let c = Complex :: new ( 2.0 , -1.0 ) ;
828
+ let r = c. log ( 10.0 ) ;
829
+ assert ! ( close_to_tol( r, Complex :: new( 0.349485 , -0.20135958 ) , 1e-5 ) ) ;
830
+ }
831
+
832
+ #[ test]
833
+ fn test_some_expf_cases ( )
834
+ {
835
+ let c = Complex :: new ( 2.0 , -1.0 ) ;
836
+ let r = c. expf ( 10.0 ) ;
837
+ assert ! ( close_to_tol( r, Complex :: new( -66.82015 , -74.39803 ) , 1e-5 ) ) ;
838
+
839
+ let c = Complex :: new ( 5.0 , -2.0 ) ;
840
+ let r = c. expf ( 3.4 ) ;
841
+ assert ! ( close_to_tol( r, Complex :: new( -349.25 , -290.63 ) , 1e-2 ) ) ;
842
+
843
+ let c = Complex :: new ( -1.5 , 2.0 / 3.0 ) ;
844
+ let r = c. expf ( 1.0 / 3.0 ) ;
845
+ assert ! ( close_to_tol( r, Complex :: new( 3.8637 , -3.4745 ) , 1e-2 ) ) ;
846
+ }
751
847
752
848
#[ test]
753
849
fn test_sqrt ( ) {
0 commit comments