Complex.st
changeset 265 f014922e3b71
child 1944 9fb0b642d2ca
equal deleted inserted replaced
264:75289d9aae94 265:f014922e3b71
       
     1 'From Smalltalk-80, Version 2.4 of 28 January 1989 on 14 May 1989 at 2:48:01 pm'!
       
     2 
       
     3 ArithmeticValue subclass: #Complex
       
     4         instanceVariableNames: 'real imaginary '
       
     5         classVariableNames: ''
       
     6         poolDictionaries: ''
       
     7         category: 'Magnitude-Numbers'
       
     8 !
       
     9 
       
    10 Complex comment:
       
    11 'This is an implementation of complex numbers.  A complex number has real and
       
    12  imaginary parts which must be manipulated simultaneously in any numeric processing.
       
    13   Complex numbers can be used in many of the same places that regular numbers
       
    14  can be used with one major exception of comparisons, since complex numbers cannot
       
    15  be directly compared for size (except through lengths of vectors (see absolute
       
    16  value)).
       
    17 
       
    18 Instance variables:
       
    19     real        <Number> the part of the number which can be expressed as a Real number
       
    20     imaginary   <Number> the part of the number which, in terms of how the number behaves,
       
    21                          has been multiplied by ''i'' (-1 sqrt)
       
    22 
       
    23 Author: Kurt Hebel (hebel@uinova.cerl.uiuc.edu)'
       
    24 !
       
    25 
       
    26 !Complex methodsFor: 'accessing'!
       
    27 
       
    28 imaginary
       
    29         "Return the imaginary part of the complex number."
       
    30         ^ imaginary
       
    31 !
       
    32 
       
    33 real
       
    34         "Return the real part of the complex number."
       
    35         ^ real
       
    36 ! !
       
    37 
       
    38 !Complex methodsFor: 'arithmetic'!
       
    39 
       
    40 * aNumber 
       
    41         "Return the product of the receiver and the argument."
       
    42 
       
    43         | u v |
       
    44 
       
    45         aNumber isComplex ifTrue:[
       
    46             u := aNumber real.
       
    47             v := aNumber imaginary.
       
    48             ^Complex real: real * u - (imaginary * v)
       
    49                      imaginary: real * v + (imaginary * u)
       
    50         ].
       
    51         ^self retry: #* coercing: aNumber
       
    52 !
       
    53 
       
    54 + aNumber 
       
    55         "Return the sum of the receiver and the argument."
       
    56 
       
    57         aNumber isComplex ifTrue: [
       
    58             ^Complex real: aNumber real + real
       
    59                      imaginary: aNumber imaginary + imaginary
       
    60         ].
       
    61         ^self retry: #+ coercing: aNumber
       
    62 !
       
    63 
       
    64 - aNumber
       
    65         "Return the difference of the receiver and the argument."
       
    66 
       
    67         aNumber isComplex ifTrue: [
       
    68             ^Complex real: real - aNumber real
       
    69                      imaginary: imaginary - aNumber imaginary
       
    70         ].
       
    71         ^self retry: #- coercing: aNumber
       
    72 !
       
    73 
       
    74 / aNumber 
       
    75         "Return the quotient of the receiver and the argument."
       
    76 
       
    77         | denom u v |
       
    78 
       
    79         aNumber isComplex ifTrue:[ 
       
    80             u := aNumber real.
       
    81             v := aNumber imaginary.
       
    82             denom := u * u + (v * v).
       
    83             ^Complex real: u * real + (v * imaginary) / denom
       
    84                      imaginary: u * imaginary - (v * real) / denom
       
    85         ].
       
    86         ^self retry: #/ coercing: aNumber
       
    87 !
       
    88 
       
    89 abs
       
    90         "Return the magnitude (or absolute value) of the complex number."
       
    91 
       
    92         ^ (real * real + (imaginary * imaginary)) sqrt
       
    93 !
       
    94 
       
    95 conjugated
       
    96         "Return the complex conjugate of this complex number."
       
    97 
       
    98         ^ Complex real: real imaginary: imaginary negated
       
    99 ! !
       
   100 
       
   101 !Complex methodsFor: 'double dispatching'!
       
   102 
       
   103 differenceFromFloat: argument
       
   104         ^ argument asComplex - self
       
   105 !
       
   106 
       
   107 differenceFromFraction: argument
       
   108         ^ argument asComplex - self
       
   109 !
       
   110 
       
   111 differenceFromInteger: argument
       
   112         ^ argument asComplex - self
       
   113 !
       
   114 
       
   115 productFromFloat: argument
       
   116         ^ argument asComplex * self
       
   117 !
       
   118 
       
   119 productFromFraction: argument
       
   120         ^ argument asComplex * self
       
   121 !
       
   122 
       
   123 productFromInteger: argument
       
   124         ^ argument asComplex * self
       
   125 !
       
   126 
       
   127 quotientFromFloat: argument
       
   128         ^ argument asComplex / self
       
   129 !
       
   130 
       
   131 quotientFromFraction: argument
       
   132         ^ argument asComplex / self
       
   133 !
       
   134 
       
   135 quotientFromInteger: argument
       
   136         ^ argument asComplex / self
       
   137 !
       
   138 
       
   139 sumFromFloat: argument
       
   140         ^ argument asComplex + self
       
   141 !
       
   142 
       
   143 sumFromFraction: argument
       
   144         ^ argument asComplex + self
       
   145 !
       
   146 
       
   147 sumFromInteger: argument
       
   148         ^ argument asComplex + self
       
   149 ! !
       
   150 
       
   151 !Complex methodsFor: 'mathematical functions'!
       
   152 
       
   153 angle
       
   154         "Return the radian angle for this Complex number."
       
   155 
       
   156         real < 0 ifTrue: [
       
   157             imaginary < 0 ifTrue: [
       
   158                 ^ (imaginary / real) arcTan - Float pi
       
   159             ].
       
   160             ^ Float pi + (imaginary / real) arcTan
       
   161         ].
       
   162         ^ (imaginary / real) arcTan
       
   163 !
       
   164 
       
   165 exp
       
   166         "Return the complex exponential of the receiver."
       
   167 
       
   168         ^ imaginary cos % imaginary sin * real exp
       
   169 !
       
   170 
       
   171 sqrt
       
   172         "Return the square root of the receiver"
       
   173 
       
   174         | u v |
       
   175         (imaginary = 0 and: [real >= 0]) ifTrue: [^real sqrt].
       
   176         v := (self abs - real / 2) sqrt.
       
   177         u := imaginary / 2 / v.
       
   178         ^Complex real: u imaginary: v
       
   179 
       
   180         "-4 asComplex sqrt"
       
   181         "-4 asComplex sqrt squared"
       
   182 ! !
       
   183 
       
   184 !Complex methodsFor: 'comparing'!
       
   185 
       
   186 = aNumber
       
   187         ^ (aNumber real = real) and:[aNumber imaginary = imaginary]
       
   188 !
       
   189 
       
   190 < aNumber
       
   191         ^Number
       
   192                 raise: #unorderedSignal
       
   193                 receiver: self
       
   194                 selector: #<
       
   195                 arg: aNumber
       
   196                 errorString: 'Complex numbers are not well ordered'!
       
   197 
       
   198 hash
       
   199         "Hash is implemented because equals is implemented."
       
   200 
       
   201         ^ real hash
       
   202 ! !
       
   203 
       
   204 !Complex methodsFor: 'testing'!
       
   205 
       
   206 isComplex
       
   207 
       
   208         ^true
       
   209 !
       
   210 
       
   211 isReal
       
   212         "Return true if this Complex number has a zero imaginary part."
       
   213         ^ imaginary = 0
       
   214 !
       
   215 
       
   216 isZero
       
   217         "Answer whether 'self = self class zero'.  We can't use #= because
       
   218         #= is defined in terms of #isZero"
       
   219 
       
   220         ^real isZero and: [imaginary isZero]
       
   221 !
       
   222 
       
   223 sign
       
   224 
       
   225         ^Complex real: real sign imaginary: imaginary sign
       
   226 ! !
       
   227 
       
   228 !Complex methodsFor: 'coercing'!
       
   229 
       
   230 coerce: aNumber
       
   231 
       
   232         ^aNumber asComplex
       
   233 !
       
   234 
       
   235 generality
       
   236 
       
   237         ^150
       
   238 ! !
       
   239 
       
   240 !Complex methodsFor: 'converting'!
       
   241 
       
   242 asComplex
       
   243 
       
   244         ^self
       
   245 !
       
   246 
       
   247 asFloat
       
   248 
       
   249         imaginary = 0 ifTrue: [^real asFloat].
       
   250         ^Number
       
   251                 raise: #coercionErrorSignal
       
   252                 receiver: self
       
   253                 selector: #asFloat
       
   254                 errorString: 'Can''t coerce an instance of Complex to a Float'
       
   255 !
       
   256 
       
   257 asInteger
       
   258 
       
   259         imaginary = 0 ifTrue: [^real asInteger].
       
   260         ^Number
       
   261                 raise: #coercionErrorSignal
       
   262                 receiver: self
       
   263                 selector: #asInteger
       
   264                 errorString: 'Can''t coerce an instance of Complex to an Integer'
       
   265 !
       
   266 
       
   267 asPoint
       
   268         "Return the complex number as a point."
       
   269         ^ real @ imaginary
       
   270 !
       
   271 
       
   272 reduceGeneralityIfPossible
       
   273         "Answer the receiver transformed to a lower generality, if such a 
       
   274         transformation is possible without losing information. If not, answer 
       
   275         the receiver"
       
   276 
       
   277         imaginary isZero
       
   278                 ifTrue: [^real]
       
   279                 ifFalse: [^self]
       
   280 ! !
       
   281 
       
   282 !Complex methodsFor: 'printing'!
       
   283 
       
   284 printString
       
   285         ^ '(' , real printString, '%', imaginary printString, ')'
       
   286 !
       
   287 
       
   288 printOn: aStream
       
   289         aStream nextPut: $(.
       
   290         real storeOn: aStream.
       
   291         aStream nextPutAll: '%'.
       
   292         imaginary storeOn: aStream.
       
   293         aStream nextPut: $).
       
   294 !
       
   295 
       
   296 storeOn: aStream
       
   297         aStream nextPut: $(.
       
   298         real storeOn: aStream.
       
   299         aStream nextPutAll: '%'.
       
   300         imaginary storeOn: aStream.
       
   301         aStream nextPut: $).
       
   302 ! !
       
   303 
       
   304 !Complex methodsFor: 'private'!
       
   305 
       
   306 setReal: u setImaginary: v
       
   307         real := u.
       
   308         imaginary := v.
       
   309 ! !
       
   310 
       
   311 
       
   312 !Complex class methodsFor: 'instance creation'!
       
   313 
       
   314 fromReal: aNumber
       
   315         "Create a new complex number from the given real number."
       
   316         ^ self basicNew setReal: aNumber setImaginary: 0
       
   317 !
       
   318 
       
   319 real: u imaginary: v
       
   320         "Create a new complex number with the given real and imaginary parts.  If the
       
   321          imaginary part is zero, return the real part of the number."
       
   322         ^v = 0 ifTrue: [u]
       
   323                ifFalse: [self basicNew setReal: u setImaginary: v]
       
   324 ! !
       
   325 
       
   326 !Complex class methodsFor: 'exception handling'!
       
   327 
       
   328 trapImaginary: aBlock
       
   329         "Complex trapImaginary: [-27 sqrt]"
       
   330 
       
   331         | send |
       
   332 
       
   333         ^Number domainErrorSignal handle: [ :ex |
       
   334             send := ex parameter.
       
   335             (send selector = #sqrt or: [send selector = #sqrtTruncated]) ifTrue: [
       
   336 	        send receiver: send receiver asComplex.
       
   337                 ex proceedWith: send value
       
   338 	    ] ifFalse: [
       
   339 		ex reject
       
   340 	    ]
       
   341 	] do: aBlock
       
   342 ! !
       
   343 
       
   344 !Complex class methodsFor: 'constants access'!
       
   345 
       
   346 unity
       
   347         "Answer the value which allows, for any given arithmetic value, the following to be true
       
   348 
       
   349          aNumber * aNumber class unity = aNumber
       
   350 
       
   351         This must be true regardless of how a given subclass chooses to define #*"
       
   352 
       
   353         ^self fromReal: 1
       
   354 !
       
   355 
       
   356 zero
       
   357         "Answer the value which allows, for any given arithmetic value, the following to be true
       
   358 
       
   359                 aNumber + aNumber class zero = aNumber
       
   360 
       
   361         This must be true regardless of how a given subclass chooses to define #+"
       
   362 
       
   363         ^self fromReal: 0
       
   364 ! !
       
   365 
       
   366 !ArithmeticValue methodsFor: 'testing'!
       
   367 
       
   368 isComplex
       
   369         "Answer whether the receiver has an imaginary part"
       
   370 
       
   371         ^false
       
   372 !
       
   373 
       
   374 isReal
       
   375         ^ true
       
   376 ! !
       
   377 
       
   378 !Number methodsFor: 'mathematical functions'!
       
   379 
       
   380 conjugated
       
   381         "Return the complex conjugate of this Number."
       
   382         ^ self
       
   383 !
       
   384 
       
   385 imaginary
       
   386         "Return the imaginary part of this Number."
       
   387         ^ 0
       
   388 !
       
   389 
       
   390 real
       
   391         "Return the real part of this Number."
       
   392         ^ self
       
   393 ! !
       
   394 
       
   395 !Number methodsFor: 'converting'!
       
   396 
       
   397 % aNumber 
       
   398         "Answer a complex number with the receiver as the real part and 
       
   399         aNumber as the imaginary part"
       
   400 
       
   401         ^Complex real: self imaginary: aNumber
       
   402 !
       
   403 
       
   404 asComplex
       
   405         "Answer a complex number with the receiver as the real part and 
       
   406         zero as the imaginary part"
       
   407 
       
   408         ^Complex fromReal: self
       
   409 ! !
       
   410 
       
   411 !Point methodsFor: 'converting'!
       
   412 
       
   413 asComplex
       
   414         "Return a complex number whose real and imaginary components are the x and y
       
   415          coordinates of the receiver."
       
   416         ^ x % y
       
   417 ! !
       
   418 
       
   419 " The above file is a Manchester Goodie.  It is distributed freely on condition
       
   420  that you observe these conditions in respect of the whole Goodie, and on
       
   421  any significant part of it which is separately transmitted or stored:
       
   422         * You must ensure that every copy includes this notice, and that
       
   423           source and author(s) of the material are acknowledged.
       
   424         * These conditions must be imposed on anyone who receives a copy.
       
   425         * The material shall not be used for commercial gain without the prior
       
   426           written consent of the author(s).
       
   427 
       
   428  For more information about the Manchester Goodies Library (from which 
       
   429  this file was distributed) send e-mail:
       
   430         To: goodies-lib@cs.man.ac.uk
       
   431         Subject: help 
       
   432 "!