Complex.st
changeset 7355 96f466eeddf5
parent 7221 b38093d749b3
child 7377 b2f13d3b9f58
equal deleted inserted replaced
7354:b22823ab2232 7355:96f466eeddf5
    20 
    20 
    21 "{ Package: 'stx:goodies' }"
    21 "{ Package: 'stx:goodies' }"
    22 
    22 
    23 ArithmeticValue subclass:#Complex
    23 ArithmeticValue subclass:#Complex
    24 	instanceVariableNames:'real imaginary'
    24 	instanceVariableNames:'real imaginary'
    25 	classVariableNames:''
    25 	classVariableNames:'ComplexOne ComplexZero'
    26 	poolDictionaries:''
    26 	poolDictionaries:''
    27 	category:'Magnitude-Numbers'
    27 	category:'Magnitude-Numbers'
    28 !
    28 !
    29 
    29 
    30 !Complex class methodsFor:'documentation'!
    30 !Complex class methodsFor:'documentation'!
    51 "
    51 "
    52 !
    52 !
    53 
    53 
    54 documentation
    54 documentation
    55 "
    55 "
    56  This is an implementation of complex numbers.  A complex number has real and
    56     This class implements complex numbers.  
    57  imaginary parts which must be manipulated simultaneously in any numeric processing.
    57     A complex number has real and imaginary parts which must be manipulated simultaneously 
    58  Complex numbers can be used in many of the same places that regular numbers
    58     in any numeric processing.
    59  can be used with one major exception of comparisons, since complex numbers cannot
    59     Complex numbers can be used in many of the same places that regular numbers
    60  be directly compared for size (except through lengths of vectors (see absolute
    60     can be used with one major exception of comparisons, since complex numbers cannot
    61  value)).
    61     be directly compared for size 
    62 
    62     (except through lengths of vectors (see absolute value)).
    63 Instance variables:
    63 
    64     real        <Number> the part of the number which can be expressed as a Real number
    64     [Instance variables:]
    65     imaginary   <Number> the part of the number which, in terms of how the number behaves,
    65        real        <Number> the part of the number which can be expressed as a Real number
    66 			 has been multiplied by 'i' (-1 sqrt)
    66        imaginary   <Number> the part of the number which, in terms of how the number behaves,
    67 
    67                             has been multiplied by 'i' (-1 sqrt)
    68 Author: Kurt Hebel (hebel@uinova.cerl.uiuc.edu)
    68 
       
    69     [Author:]
       
    70         Kurt Hebel (hebel@uinova.cerl.uiuc.edu)
       
    71         minor changes and double dispatching code by cg.
    69 "
    72 "
    70 !
    73 !
    71 
    74 
    72 example
    75 examples
    73 "
    76 "
    74     (5 % 7) real
    77     (5 % 7) real
    75     (5 % 7) imaginary
    78     (5 % 7) imaginary
    76     (5 % 7) = 5
    79     (5 % 7) = 5
    77     (5 % 0) = 5     
    80     (5 % 0) = 5     
    82     (1 % 0) + (2 % 3)
    85     (1 % 0) + (2 % 3)
    83 
    86 
    84     (1 % 0) * (2 % 0)   
    87     (1 % 0) * (2 % 0)   
    85     (1 % 0) * (0 % 2)   
    88     (1 % 0) * (0 % 2)   
    86     (1 % 0) * (2 % 3)
    89     (1 % 0) * (2 % 3)
       
    90 
       
    91     (1 % 2) + 2
       
    92     (1 % 2) * 2
       
    93     2 + (1 % 2) 
       
    94     2 * (1 % 2) 
       
    95 
    87 "
    96 "
    88 ! !
    97 ! !
    89 
    98 
    90 !Complex class methodsFor:'instance creation'!
    99 !Complex class methodsFor:'instance creation'!
    91 
   100 
    92 fromReal: aNumber
   101 fromReal: aNumber
    93 	"Create a new complex number from the given real number."
   102     "Create a new complex number from the given real number."
    94 	^ self basicNew setReal: aNumber setImaginary: 0
   103 
       
   104     ^ self basicNew setReal: aNumber setImaginary: 0
       
   105 !
       
   106 
       
   107 imaginary: v
       
   108     "Create a new complex number with 0 as real and given imaginary parts.
       
   109      If the imaginary part is zero, return the real part of the number."
       
   110 
       
   111     v = 0 ifTrue: [^ 0].
       
   112     ^ self basicNew setReal: 0 setImaginary: v
       
   113 !
       
   114 
       
   115 real: aNumber
       
   116     "Create a new complex number from the given real number."
       
   117 
       
   118     ^ self basicNew setReal: aNumber setImaginary: 0
    95 !
   119 !
    96 
   120 
    97 real: u imaginary: v
   121 real: u imaginary: v
    98 	"Create a new complex number with the given real and imaginary parts.  If the
   122     "Create a new complex number with the given real and imaginary parts.  If the
    99 	 imaginary part is zero, return the real part of the number."
   123      imaginary part is zero, return the real part of the number."
   100 	^v = 0 ifTrue: [u]
   124 
   101 	       ifFalse: [self basicNew setReal: u setImaginary: v]
   125     v = 0 ifTrue: [^ u].
       
   126     ^ self basicNew setReal: u setImaginary: v
   102 ! !
   127 ! !
   103 
   128 
   104 !Complex class methodsFor:'constants access'!
   129 !Complex class methodsFor:'constants access'!
   105 
   130 
   106 unity
   131 unity
   107 	"Answer the value which allows, for any given arithmetic value, the following to be true
   132     "Answer the value which allows, for any given arithmetic value, the following to be true:
   108 
   133         aNumber * aNumber class unity = aNumber
   109 	 aNumber * aNumber class unity = aNumber
   134      This must be true regardless of how a given subclass chooses to define #*"
   110 
   135 
   111 	This must be true regardless of how a given subclass chooses to define #*"
   136     ComplexOne isNil ifTrue:[
   112 
   137         ComplexOne := self fromReal: 1
   113 	^self fromReal: 1
   138     ].
       
   139     ^ ComplexOne
   114 !
   140 !
   115 
   141 
   116 zero
   142 zero
   117 	"Answer the value which allows, for any given arithmetic value, the following to be true
   143     "Answer the value which allows, for any given arithmetic value, the following to be true:
   118 
   144         aNumber + aNumber class zero = aNumber
   119 		aNumber + aNumber class zero = aNumber
   145      This must be true regardless of how a given subclass chooses to define #+"
   120 
   146 
   121 	This must be true regardless of how a given subclass chooses to define #+"
   147     ComplexZero isNil ifTrue:[
   122 
   148         ComplexZero := self fromReal: 0
   123 	^self fromReal: 0
   149     ].
       
   150     ^ ComplexZero
   124 ! !
   151 ! !
   125 
   152 
   126 !Complex class methodsFor:'exception handling'!
   153 !Complex class methodsFor:'exception handling'!
   127 
   154 
   128 trapImaginary: aBlock
   155 trapImaginary: aBlock
   142 ! !
   169 ! !
   143 
   170 
   144 !Complex methodsFor:'accessing'!
   171 !Complex methodsFor:'accessing'!
   145 
   172 
   146 imaginary
   173 imaginary
   147 	"Return the imaginary part of the complex number."
   174     "Return the imaginary part of the complex number."
   148 	^ imaginary
   175 
       
   176     ^ imaginary
       
   177 !
       
   178 
       
   179 imaginaryPart
       
   180     "Return the imaginary part of the complex number.
       
   181      An alias for imaginary (for compatibility with other complex implementations)"
       
   182 
       
   183     ^ imaginary
   149 !
   184 !
   150 
   185 
   151 real
   186 real
   152 	"Return the real part of the complex number."
   187     "Return the real part of the complex number."
   153 	^ real
   188 
       
   189     ^ real
       
   190 !
       
   191 
       
   192 realPart
       
   193     "Return the real part of the complex number.
       
   194      An alias for real (for compatibility with other complex implementations)"
       
   195 
       
   196     ^ real
   154 ! !
   197 ! !
   155 
   198 
   156 !Complex methodsFor:'arithmetic'!
   199 !Complex methodsFor:'arithmetic'!
   157 
   200 
   158 * aNumber 
   201 * aNumber 
   159 	"Return the product of the receiver and the argument."
   202     "Return the product of the receiver and the argument."
   160 
   203 
   161 	| u v r i |
   204 "/    | u v r i |
   162 
   205 "/
   163 	aNumber isComplex ifTrue:[
   206 "/    aNumber isComplex ifTrue:[
   164 	    u := aNumber real.
   207 "/        u := aNumber real.
   165 	    v := aNumber imaginary.
   208 "/        v := aNumber imaginary.
   166 	    r := (real * u) - (imaginary * v).
   209 "/        r := (real * u) - (imaginary * v).
   167 	    i  := (real * v) + (imaginary * u).
   210 "/        i  := (real * v) + (imaginary * u).
   168 	    i = 0 ifTrue:[ ^ r ].
   211 "/        i = 0 ifTrue:[ ^ r ].
   169 	    ^ Complex real:r imaginary:i
   212 "/        ^ Complex real:r imaginary:i
   170 	].
   213 "/    ].
   171 	^ self retry: #* coercing: aNumber
   214     ^ aNumber productFromComplex:self. 
   172 
   215 
   173     "Modified: / 8.7.1998 / 12:12:37 / cg"
   216     "Modified: / 8.7.1998 / 12:12:37 / cg"
   174 !
   217 !
   175 
   218 
   176 + aNumber 
   219 + aNumber 
   177 	"Return the sum of the receiver and the argument."
   220     "Return the sum of the receiver and the argument."
   178 
   221 
   179 	| r i |
   222 "/    | r i |
   180 
   223 "/
   181 	aNumber isComplex ifTrue: [
   224 "/    aNumber isComplex ifTrue: [
   182 	    r := aNumber real + real.
   225 "/        r := aNumber real + real.
   183 	    i := aNumber imaginary + imaginary.
   226 "/        i := aNumber imaginary + imaginary.
   184 	    i = 0 ifTrue:[ ^ r ].
   227 "/        i = 0 ifTrue:[ ^ r ].
   185 	    ^ Complex real:r imaginary:i
   228 "/        ^ Complex real:r imaginary:i
   186 	].
   229 "/    ].
   187 	^ self retry: #+ coercing: aNumber
   230     ^ aNumber sumFromComplex:self. 
   188 
   231 
   189     "Modified: / 8.7.1998 / 12:15:42 / cg"
   232     "Modified: / 8.7.1998 / 12:15:42 / cg"
   190 !
   233 !
   191 
   234 
   192 - aNumber
   235 - aNumber
   193 	"Return the difference of the receiver and the argument."
   236     "Return the difference of the receiver and the argument."
   194 
   237 
   195 	| r i |
   238 "/    | r i |
   196 
   239 "/
   197 	aNumber isComplex ifTrue: [
   240 "/    aNumber isComplex ifTrue: [
   198 	    r := real - aNumber real.
   241 "/        r := real - aNumber real.
   199 	    i := imaginary - aNumber imaginary.
   242 "/        i := imaginary - aNumber imaginary.
   200 	    i = 0 ifTrue:[ ^ r ].
   243 "/        i = 0 ifTrue:[ ^ r ].
   201 	    ^ Complex real:r imaginary:i.
   244 "/        ^ Complex real:r imaginary:i.
   202 	].
   245 "/    ].
   203 	^ self retry: #- coercing: aNumber
   246     ^ aNumber differenceFromComplex:self. 
   204 
   247 
   205     "Modified: / 8.7.1998 / 12:15:38 / cg"
   248     "Modified: / 8.7.1998 / 12:15:38 / cg"
   206 !
   249 !
   207 
   250 
   208 / aNumber 
   251 / aNumber 
   209 	"Return the quotient of the receiver and the argument."
   252     "Return the quotient of the receiver and the argument."
   210 
   253 
   211 	| denom u v r i |
   254 "/    | denom u v r i |
   212 
   255 "/
   213 	aNumber isComplex ifTrue:[ 
   256 "/    aNumber isComplex ifTrue:[ 
   214 	    u := aNumber real.
   257 "/        u := aNumber real.
   215 	    v := aNumber imaginary.
   258 "/        v := aNumber imaginary.
   216 	    denom := u * u + (v * v).
   259 "/        denom := u * u + (v * v).
   217 	    r := u * real + (v * imaginary) / denom.
   260 "/        r := u * real + (v * imaginary) / denom.
   218 	    i := u * imaginary - (v * real) / denom.
   261 "/        i := u * imaginary - (v * real) / denom.
   219 	    i = 0 ifTrue:[ ^ r ].
   262 "/        i = 0 ifTrue:[ ^ r ].
   220 	    ^ Complex real:r imaginary:i
   263 "/        ^ Complex real:r imaginary:i
   221 	].
   264 "/    ].
   222 	^ self retry: #/ coercing: aNumber
   265     ^ aNumber quotientFromComplex:self. 
   223 
   266 
   224     "Modified: / 8.7.1998 / 12:15:34 / cg"
   267     "Modified: / 8.7.1998 / 12:15:34 / cg"
   225 !
   268 !
   226 
   269 
   227 abs
   270 abs
   228 	"Return the magnitude (or absolute value) of the complex number."
   271     "Return the magnitude (or absolute value) of the complex number
   229 
   272      (thats the distance from the origin in the complex plane)."
   230 	^ (real * real + (imaginary * imaginary)) sqrt
   273 
       
   274     ^ (real * real + (imaginary * imaginary)) sqrt
       
   275 
       
   276     "
       
   277      (1 % 1) abs
       
   278     "
   231 !
   279 !
   232 
   280 
   233 conjugated
   281 conjugated
   234 	"Return the complex conjugate of this complex number."
   282     "Return the complex conjugate of this complex number
   235 
   283      (i.e. with imaginary part negated)."
   236 	^ Complex real: real imaginary: imaginary negated
   284 
       
   285     ^ Complex 
       
   286         real: real
       
   287         imaginary: imaginary negated
       
   288 !
       
   289 
       
   290 differenceFromComplex:aComplex
       
   291     "Return the difference of the argument, aComplex and the receiver."
       
   292 
       
   293     | r i |
       
   294 
       
   295     r := aComplex real - real.
       
   296     i := aComplex imaginary - imaginary.
       
   297     i = 0 ifTrue:[ ^ r ].
       
   298     ^ Complex real:r imaginary:i.
       
   299 !
       
   300 
       
   301 modulus
       
   302     | absReal absImag multiplicand quotient |
       
   303 
       
   304     absReal := real abs.
       
   305     absImag := imaginary abs.
       
   306 
       
   307     absReal >= absImag ifTrue: [ 
       
   308         multiplicand := absReal.  
       
   309         quotient := imaginary / real 
       
   310     ] ifFalse: [ 
       
   311         multiplicand := absImag.  
       
   312         quotient := real / imaginary 
       
   313     ].
       
   314     ^ multiplicand * ((1 + (quotient * quotient)) sqrt)
       
   315 !
       
   316 
       
   317 negated
       
   318     "return a new complex with both real and imaginary parts negated"
       
   319 
       
   320     ^ Complex 
       
   321         real: real negated 
       
   322         imaginary: imaginary negated
       
   323 !
       
   324 
       
   325 productFromComplex:aComplex 
       
   326     "Return the product of the receiver and the argument, aComplex."
       
   327 
       
   328     | u v r i |
       
   329 
       
   330     u := aComplex real.
       
   331     v := aComplex imaginary.
       
   332     r := (real * u) - (imaginary * v).
       
   333     i  := (real * v) + (imaginary * u).
       
   334     i = 0 ifTrue:[ ^ r ].
       
   335     ^ Complex real:r imaginary:i
       
   336 !
       
   337 
       
   338 quotientFromComplex:aComplex 
       
   339     "Return the quotient of the argument, aComplex and the receiver."
       
   340 
       
   341     | denom nr ni r i |
       
   342 
       
   343     nr := aComplex real.
       
   344     ni := aComplex imaginary.
       
   345     denom := real * real + (imaginary * imaginary).
       
   346     r := real * nr + (imaginary * ni) / denom.
       
   347     i := real * ni - (imaginary * nr) / denom.
       
   348     i = 0 ifTrue:[ ^ r ].
       
   349     ^ Complex real:r imaginary:i
       
   350 
       
   351 "/ is the stuff below better ?
       
   352 "/    "Implement complex division (a + ib) / (c + id).  
       
   353 "/     Due to double dispatch, in this routine
       
   354 "/        self = (c + id) and aComplex = (a + ib)."
       
   355 "/
       
   356 "/    | quotient denominator |
       
   357 "/
       
   358 "/    self realPart abs >= (self imaginaryPart abs)
       
   359 "/        ifTrue: [ 
       
   360 "/            quotient := self imaginaryPart / self realPart.
       
   361 "/            denominator := self realPart + (self imaginaryPart * quotient).
       
   362 "/            ^ Complex 
       
   363 "/                real: (aComplex realPart + (aComplex imaginaryPart * quotient)) / denominator
       
   364 "/                imaginary: (aComplex imaginaryPart - (aComplex realPart * quotient)) / denominator ]
       
   365 "/        ifFalse: [ 
       
   366 "/            quotient := self realPart / self imaginaryPart.
       
   367 "/            denominator := (self realPart * quotient) + self imaginaryPart.
       
   368 "/            ^ Complex 
       
   369 "/                real: ((aComplex realPart * quotient) + aComplex imaginaryPart) / denominator
       
   370 "/                imaginary: ((aComplex imaginaryPart * quotient) - aComplex realPart) / denominator ]
       
   371 !
       
   372 
       
   373 sumFromComplex:aComplex 
       
   374     "Return the sum of the receiver and the argument, aComplex."
       
   375 
       
   376     | r i |
       
   377 
       
   378     r := aComplex real + real.
       
   379     i := aComplex imaginary + imaginary.
       
   380     i = 0 ifTrue:[ ^ r ].
       
   381     ^ Complex real:r imaginary:i
   237 ! !
   382 ! !
   238 
   383 
   239 !Complex methodsFor:'coercing'!
   384 !Complex methodsFor:'coercing'!
   240 
   385 
   241 coerce: aNumber
   386 coerce: aNumber
   242 
   387     ^ aNumber asComplex
   243 	^aNumber asComplex
       
   244 !
   388 !
   245 
   389 
   246 generality
   390 generality
   247 
   391     ^ 150
   248 	^150
       
   249 ! !
   392 ! !
   250 
   393 
   251 !Complex methodsFor:'comparing'!
   394 !Complex methodsFor:'comparing'!
   252 
   395 
   253 < aNumber
   396 < aNumber
   254 	^Number
   397     "raises an error - complex numbers are not well ordered"
   255 		raise: #unorderedSignal
   398 
   256 		receiver: self
   399     ^ Number
   257 		selector: #<
   400         raise: #unorderedSignal
   258 		arg: aNumber
   401         receiver: self
   259 		errorString: 'Complex numbers are not well ordered'
   402         selector: #<
       
   403         arg: aNumber
       
   404         errorString: 'Complex numbers are not well ordered'
       
   405 
       
   406     "
       
   407      1 < (2 % 2)
       
   408      (2 % 2) < 1
       
   409     "
   260 !
   410 !
   261 
   411 
   262 = aNumber
   412 = aNumber
   263 	^ (aNumber real = real) and:[aNumber imaginary = imaginary]
   413     "return true, if the argument represents the same numeric value
       
   414      as the receiver, false otherwise"
       
   415 
       
   416     ^ aNumber equalFromComplex:self    
   264 !
   417 !
   265 
   418 
   266 hash
   419 hash
   267 	"Hash is implemented because equals is implemented."
   420     "Hash is implemented because equals is implemented."
   268 
   421 
   269 	^ real hash
   422     ^ real hash
   270 ! !
   423 ! !
   271 
   424 
   272 !Complex methodsFor:'converting'!
   425 !Complex methodsFor:'converting'!
   273 
   426 
   274 asComplex
   427 asComplex
   275 
   428     "I am a complex - so return the receiver"
   276 	^self
   429 
       
   430     ^ self
   277 !
   431 !
   278 
   432 
   279 asFloat
   433 asFloat
   280 
   434     imaginary = 0 ifTrue: [^ real asFloat].
   281 	imaginary = 0 ifTrue: [^real asFloat].
   435     ^ Number
   282 	^Number
   436             raise: #coercionErrorSignal
   283 		raise: #coercionErrorSignal
   437             receiver: self
   284 		receiver: self
   438             selector: #asFloat
   285 		selector: #asFloat
   439             errorString: 'Can''t coerce an instance of Complex to a Float'
   286 		errorString: 'Can''t coerce an instance of Complex to a Float'
       
   287 !
   440 !
   288 
   441 
   289 asInteger
   442 asInteger
   290 
   443     imaginary = 0 ifTrue: [^real asInteger].
   291 	imaginary = 0 ifTrue: [^real asInteger].
   444     ^ Number
   292 	^Number
   445         raise: #coercionErrorSignal
   293 		raise: #coercionErrorSignal
   446         receiver: self
   294 		receiver: self
   447         selector: #asInteger
   295 		selector: #asInteger
   448         errorString: 'Can''t coerce an instance of Complex to an Integer'
   296 		errorString: 'Can''t coerce an instance of Complex to an Integer'
       
   297 !
   449 !
   298 
   450 
   299 asPoint
   451 asPoint
   300 	"Return the complex number as a point."
   452     "Return the complex number as a point."
   301 	^ real @ imaginary
   453 
       
   454     ^ real @ imaginary
   302 !
   455 !
   303 
   456 
   304 reduceGeneralityIfPossible
   457 reduceGeneralityIfPossible
   305 	"Answer the receiver transformed to a lower generality, if such a 
   458     "Answer the receiver transformed to a lower generality, if such a 
   306 	transformation is possible without losing information. If not, answer 
   459      transformation is possible without losing information. 
   307 	the receiver"
   460      If not, answer the receiver"
   308 
   461 
   309 	imaginary isZero
   462     imaginary isZero
   310 		ifTrue: [^real]
   463         ifTrue: [^ real]
   311 		ifFalse: [^self]
   464         ifFalse: [^ self]
   312 ! !
   465 ! !
   313 
   466 
   314 !Complex methodsFor:'double dispatching'!
   467 !Complex methodsFor:'double dispatching'!
   315 
   468 
   316 differenceFromFloat: argument
   469 differenceFromFloat:aFloat
   317 	^ argument asComplex - self
   470     "Return the difference of the argument, aFloat and the receiver."
   318 !
   471 
   319 
   472     "/ ^ aFloat asComplex - self
   320 differenceFromFraction: argument
   473 
   321 	^ argument asComplex - self
   474     | r |
   322 !
   475 
   323 
   476     r := aFloat - real.
   324 differenceFromInteger: argument
   477     imaginary = 0 ifTrue:[ ^ r ].
   325 	^ argument asComplex - self
   478     ^ Complex real:r imaginary:imaginary
   326 !
   479 
   327 
   480     "
   328 productFromFloat: argument
   481      (1 % 1) - 1.0 
   329 	^ argument asComplex * self
   482      1.0 - (1 % 1) 
   330 !
   483     "
   331 
   484 !
   332 productFromFraction: argument
   485 
   333 	^ argument asComplex * self
   486 differenceFromFraction: aFraction
   334 !
   487     ^ aFraction asComplex - self
   335 
   488 !
   336 productFromInteger: argument
   489 
   337 	^ argument asComplex * self
   490 differenceFromInteger: anInteger
   338 !
   491     ^ anInteger asComplex - self
   339 
   492 !
   340 quotientFromFloat: argument
   493 
   341 	^ argument asComplex / self
   494 equalFromComplex:aComplex
   342 !
   495     ^ (aComplex real = real) and:[aComplex imaginary = imaginary]
   343 
   496 !
   344 quotientFromFraction: argument
   497 
   345 	^ argument asComplex / self
   498 equalFromFloat:aFloat
   346 !
   499     imaginary = 0 ifFalse:[^ false].
   347 
   500     ^ real = aFloat
   348 quotientFromInteger: argument
   501 !
   349 	^ argument asComplex / self
   502 
   350 !
   503 productFromFloat: aFloat
   351 
   504     "Return the product of the receiver and the argument, aFloat."
   352 sumFromFloat: argument
   505 
   353 	^ argument asComplex + self
   506     "/  ^ aFloat asComplex * self
   354 !
   507 
   355 
   508     | u r i |
   356 sumFromFraction: argument
   509 
   357 	^ argument asComplex + self
   510     u := aFloat.
   358 !
   511     r := (real * aFloat).
   359 
   512     i  := (imaginary * aFloat).
   360 sumFromInteger: argument
   513     i = 0 ifTrue:[ ^ r ].
   361 	^ argument asComplex + self
   514     ^ Complex real:r imaginary:i
       
   515 
       
   516     "
       
   517      (1 % 1) * 2.0 
       
   518      (1 % 1) * 0.0 
       
   519      2.0 * (1 % 1)
       
   520     "
       
   521 !
       
   522 
       
   523 productFromFraction: aFraction
       
   524     ^ aFraction asComplex * self
       
   525 !
       
   526 
       
   527 productFromInteger: anInteger
       
   528     ^ anInteger asComplex * self
       
   529 !
       
   530 
       
   531 quotientFromFloat: aFloat
       
   532     ^ aFloat asComplex / self
       
   533 !
       
   534 
       
   535 quotientFromFraction: aFraction
       
   536     ^ aFraction asComplex / self
       
   537 !
       
   538 
       
   539 quotientFromInteger: anInteger
       
   540     ^ anInteger asComplex / self
       
   541 !
       
   542 
       
   543 sumFromFloat: aFloat
       
   544     "Return the sum of the receiver and the argument, aFloat."
       
   545 
       
   546     "/ ^ aFloat asComplex + self
       
   547 
       
   548     | r |
       
   549 
       
   550     r := aFloat + real.
       
   551     imaginary = 0 ifTrue:[ ^ r ].
       
   552     ^ Complex real:r imaginary:imaginary
       
   553 
       
   554     "
       
   555      (1 % 1) + 1.0  
       
   556      1.0 + (1 % 1)  
       
   557     "
       
   558 !
       
   559 
       
   560 sumFromFraction: aFraction
       
   561     ^ aFraction asComplex + self
       
   562 !
       
   563 
       
   564 sumFromInteger: anInteger
       
   565     ^ anInteger asComplex + self
   362 ! !
   566 ! !
   363 
   567 
   364 !Complex methodsFor:'mathematical functions'!
   568 !Complex methodsFor:'mathematical functions'!
   365 
   569 
   366 angle
   570 angle
   367 	"Return the radian angle for this Complex number."
   571     "Return the radian angle for this Complex number."
   368 
   572 
   369 	real < 0 ifTrue: [
   573     real < 0 ifTrue: [
   370 	    imaginary < 0 ifTrue: [
   574         imaginary < 0 ifTrue: [
   371 		^ (imaginary / real) arcTan - Float pi
   575             ^ (imaginary / real) arcTan - Float pi
   372 	    ].
   576         ].
   373 	    ^ Float pi + (imaginary / real) arcTan
   577         ^ Float pi + (imaginary / real) arcTan
   374 	].
   578     ].
   375 	^ (imaginary / real) arcTan
   579     ^ (imaginary / real) arcTan
       
   580 
       
   581     "
       
   582      (1 % 1) angle radiansToDegrees
       
   583     "
   376 !
   584 !
   377 
   585 
   378 exp
   586 exp
   379 	"Return the complex exponential of the receiver."
   587     "Return the complex exponential of the receiver."
   380 
   588 
   381 	^ imaginary cos % imaginary sin * real exp
   589     ^ (imaginary cos % imaginary sin) * real exp
   382 !
   590 !
   383 
   591 
   384 sqrt
   592 sqrt
   385 	"Return the square root of the receiver"
   593     "Return the square root of the receiver"
   386 
   594 
   387 	| u v |
   595     | w quotient absReal absImag |
   388 	(imaginary = 0 and: [real >= 0]) ifTrue: [^real sqrt].
   596 
   389 	v := (self abs - real / 2) sqrt.
   597     ((real = 0) and: [ imaginary = 0 ]) ifTrue: [ 
   390 	u := imaginary / 2 / v.
   598         ^ Complex zero 
   391 	^Complex real: u imaginary: v
   599     ].
   392 
   600     absReal := real abs.
   393 	"-4 asComplex sqrt"
   601     absImag := imaginary abs.
   394 	"-4 asComplex sqrt squared"
   602 
       
   603     absReal >= absImag ifTrue:[ 
       
   604         quotient := imaginary / real.
       
   605         w := (absReal sqrt) * (((1 + (1 + (quotient * quotient)) sqrt) / 2) sqrt) 
       
   606     ] ifFalse: [ 
       
   607         quotient := real / imaginary.
       
   608         w := (absImag sqrt) * (((quotient abs + (1 + (quotient * quotient)) sqrt) / 2) sqrt) 
       
   609     ].
       
   610 
       
   611     real >= 0 ifTrue:[ 
       
   612         ^ Complex real: w imaginary: (imaginary / (2 * w)) 
       
   613     ].
       
   614     imaginary >= 0 ifTrue: [ 
       
   615         ^ Complex real: absImag / (2 * w) imaginary: w 
       
   616     ].
       
   617     ^ Complex real: absImag / (2 * w) imaginary: -1 * w
       
   618 !
       
   619 
       
   620 sqrt_bad
       
   621     "Return the square root of the receiver"
       
   622 
       
   623     | u v |
       
   624 
       
   625     (imaginary = 0 and: [real >= 0]) ifTrue: [^ real sqrt].
       
   626     v := (self abs - real / 2) sqrt.
       
   627     u := imaginary / 2 / v.
       
   628     ^ Complex real: u imaginary: v
       
   629 
       
   630     "
       
   631      -4 asComplex sqrt   
       
   632      4 asComplex sqrt   
       
   633     "
       
   634     "
       
   635      -4 asComplex sqrt squared 
       
   636     "
   395 ! !
   637 ! !
   396 
   638 
   397 !Complex methodsFor:'printing'!
   639 !Complex methodsFor:'printing'!
   398 
   640 
       
   641 displayOn: aStream
       
   642     aStream nextPut: $(.
       
   643     self realPart printOn: aStream.
       
   644     self imaginaryPart >= 0
       
   645         ifTrue: [ aStream nextPut: $+ ]
       
   646         ifFalse: [ aStream nextPut: $- ].
       
   647     self imaginaryPart abs printOn: aStream.
       
   648     aStream nextPutAll: 'i)'
       
   649 
       
   650     "
       
   651      Complex real:1 imaginary:1
       
   652     "
       
   653 !
       
   654 
   399 printOn: aStream
   655 printOn: aStream
   400 	aStream nextPut: $(.
   656     aStream nextPut: $(.
   401 	real storeOn: aStream.
   657     real storeOn: aStream.
   402 	aStream nextPutAll: '%'.
   658     aStream nextPutAll: '%'.
   403 	imaginary storeOn: aStream.
   659     imaginary storeOn: aStream.
   404 	aStream nextPut: $).
   660     aStream nextPut: $).
   405 !
   661 !
   406 
   662 
   407 printString
   663 printString
   408 	^ '(' , real printString, '%', imaginary printString, ')'
   664     ^ '(' , real printString, '%', imaginary printString, ')'
   409 !
   665 !
   410 
   666 
   411 storeOn: aStream
   667 storeOn: aStream
   412 	aStream nextPut: $(.
   668     self printOn:aStream
   413 	real storeOn: aStream.
       
   414 	aStream nextPutAll: '%'.
       
   415 	imaginary storeOn: aStream.
       
   416 	aStream nextPut: $).
       
   417 ! !
   669 ! !
   418 
   670 
   419 !Complex methodsFor:'private'!
   671 !Complex methodsFor:'private'!
   420 
   672 
   421 setReal: u setImaginary: v
   673 setReal: u setImaginary: v
   422 	real := u.
   674     real := u.
   423 	imaginary := v.
   675     imaginary := v.
   424 ! !
   676 ! !
   425 
   677 
   426 !Complex methodsFor:'testing'!
   678 !Complex methodsFor:'testing'!
   427 
   679 
   428 isComplex
   680 isComplex
   429 
   681     "Answer whether the receiver has an imaginary part
   430 	^true
   682      (i.e. if it is a complex number). Always true here."
       
   683 
       
   684     ^ true
   431 !
   685 !
   432 
   686 
   433 isReal
   687 isReal
   434 	"Return true if this Complex number has a zero imaginary part."
   688     "Return true if this Complex number has a zero imaginary part."
   435 	^ imaginary = 0
   689 
       
   690     ^ imaginary = 0
   436 !
   691 !
   437 
   692 
   438 isZero
   693 isZero
   439 	"Answer whether 'self = self class zero'.  We can't use #= because
   694     "Answer whether 'self = self class zero'.  
   440 	#= is defined in terms of #isZero"
   695      We can't use #= because #= is defined in terms of #isZero"
   441 
   696 
   442 	^real isZero and: [imaginary isZero]
   697     ^real isZero and: [imaginary isZero]
   443 !
   698 !
   444 
   699 
   445 sign
   700 sign
   446 
   701     "return a new complex, consisting of the signs of the real and imaginary parts"
   447 	^Complex real: real sign imaginary: imaginary sign
   702 
       
   703     ^ Complex real: real sign imaginary: imaginary sign
       
   704 ! !
       
   705 
       
   706 !Complex methodsFor:'truncation & rounding'!
       
   707 
       
   708 ceiling
       
   709     "blocked: complex numbers have no ceiling"
       
   710 
       
   711     ^ self shouldNotImplement
       
   712 !
       
   713 
       
   714 floor
       
   715     "blocked: complex numbers have no floor"
       
   716 
       
   717     ^ self shouldNotImplement
   448 ! !
   718 ! !
   449 
   719 
   450 !Complex class methodsFor:'documentation'!
   720 !Complex class methodsFor:'documentation'!
   451 
   721 
   452 version
   722 version
   453     ^ '$Header: /cvs/stx/stx/libbasic/Complex.st,v 1.7 2003-04-22 09:44:13 cg Exp $'
   723     ^ '$Header: /cvs/stx/stx/libbasic/Complex.st,v 1.8 2003-06-16 09:13:42 cg Exp $'
   454 ! !
   724 ! !