@@ -731,18 +731,21 @@ impl<T: Clone + Num> Div<Complex<T>> for Complex<T> {
731731
732732forward_all_binop ! ( impl Rem , rem) ;
733733
734- // Attempts to identify the gaussian integer whose product with `modulus`
735- // is closest to `self`.
734+ impl < T : Clone + Num > Complex < T > {
735+ /// Find the gaussian integer corresponding to the true ratio rounded towards zero.
736+ fn div_trunc ( & self , divisor : & Self ) -> Self {
737+ let Complex { re, im } = self / divisor;
738+ Complex :: new ( re. clone ( ) - re % T :: one ( ) , im. clone ( ) - im % T :: one ( ) )
739+ }
740+ }
741+
736742impl < T : Clone + Num > Rem < Complex < T > > for Complex < T > {
737743 type Output = Self ;
738744
739745 #[ inline]
740746 fn rem ( self , modulus : Self ) -> Self :: Output {
741- let Complex { re, im } = self . clone ( ) / modulus. clone ( ) ;
742- // This is the gaussian integer corresponding to the true ratio
743- // rounded towards zero.
744- let ( re0, im0) = ( re. clone ( ) - re % T :: one ( ) , im. clone ( ) - im % T :: one ( ) ) ;
745- self - modulus * Self :: Output :: new ( re0, im0)
747+ let gaussian = self . div_trunc ( & modulus) ;
748+ self - modulus * gaussian
746749 }
747750}
748751
@@ -769,9 +772,16 @@ mod opassign {
769772 }
770773 }
771774
775+ // (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
772776 impl < T : Clone + NumAssign > MulAssign for Complex < T > {
773777 fn mul_assign ( & mut self , other : Self ) {
774- * self = self . clone ( ) * other;
778+ let a = self . re . clone ( ) ;
779+
780+ self . re *= other. re . clone ( ) ;
781+ self . re -= self . im . clone ( ) * other. im . clone ( ) ;
782+
783+ self . im *= other. re ;
784+ self . im += a * other. im ;
775785 }
776786 }
777787
@@ -797,15 +807,27 @@ mod opassign {
797807 }
798808 }
799809
810+ // (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
811+ // == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
800812 impl < T : Clone + NumAssign > DivAssign for Complex < T > {
801813 fn div_assign ( & mut self , other : Self ) {
802- * self = self . clone ( ) / other;
814+ let a = self . re . clone ( ) ;
815+ let norm_sqr = other. norm_sqr ( ) ;
816+
817+ self . re *= other. re . clone ( ) ;
818+ self . re += self . im . clone ( ) * other. im . clone ( ) ;
819+ self . re /= norm_sqr. clone ( ) ;
820+
821+ self . im *= other. re ;
822+ self . im -= a * other. im ;
823+ self . im /= norm_sqr;
803824 }
804825 }
805826
806827 impl < T : Clone + NumAssign > RemAssign for Complex < T > {
807- fn rem_assign ( & mut self , other : Self ) {
808- * self = self . clone ( ) % other;
828+ fn rem_assign ( & mut self , modulus : Self ) {
829+ let gaussian = self . div_trunc ( & modulus) ;
830+ * self -= modulus * gaussian;
809831 }
810832 }
811833
@@ -837,7 +859,8 @@ mod opassign {
837859
838860 impl < T : Clone + NumAssign > RemAssign < T > for Complex < T > {
839861 fn rem_assign ( & mut self , other : T ) {
840- * self = self . clone ( ) % other;
862+ self . re %= other. clone ( ) ;
863+ self . im %= other;
841864 }
842865 }
843866
@@ -862,19 +885,7 @@ mod opassign {
862885 forward_op_assign ! ( impl SubAssign , sub_assign) ;
863886 forward_op_assign ! ( impl MulAssign , mul_assign) ;
864887 forward_op_assign ! ( impl DivAssign , div_assign) ;
865-
866- impl < ' a , T : Clone + NumAssign > RemAssign < & ' a Complex < T > > for Complex < T > {
867- #[ inline]
868- fn rem_assign ( & mut self , other : & Self ) {
869- self . rem_assign ( other. clone ( ) )
870- }
871- }
872- impl < ' a , T : Clone + NumAssign > RemAssign < & ' a T > for Complex < T > {
873- #[ inline]
874- fn rem_assign ( & mut self , other : & T ) {
875- self . rem_assign ( other. clone ( ) )
876- }
877- }
888+ forward_op_assign ! ( impl RemAssign , rem_assign) ;
878889}
879890
880891impl < T : Clone + Num + Neg < Output = T > > Neg for Complex < T > {
0 commit comments