Class: Complex

Inherits:
Numeric show all
Defined in:
lib/complex.rb

Overview

The complex number class. See complex.rb for an overview.

Constant Summary collapse

I =

I is the imaginary number. It exists at point (0,1) on the complex plane.

Complex(0,1)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Numeric

#im

Constructor Details

#initialize(a, b) ⇒ Complex

Returns a new instance of Complex.

Raises:

  • (TypeError)


128
129
130
131
132
133
134
135
# File 'lib/complex.rb', line 128

def initialize(a, b)
  raise TypeError, "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
  raise TypeError, "`#{a.inspect}' for 1st arg" if a.kind_of? Complex
  raise TypeError, "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
  raise TypeError, "`#{b.inspect}' for 2nd arg" if b.kind_of? Complex
  @real = a
  @image = b
end

Instance Attribute Details

#imageObject (readonly) Also known as: imag

The imaginary part of a complex number.



413
414
415
# File 'lib/complex.rb', line 413

def image
  @image
end

#realObject (readonly)

The real part of a complex number.



410
411
412
# File 'lib/complex.rb', line 410

def real
  @real
end

Class Method Details

.generic?(other) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


108
109
110
111
112
# File 'lib/complex.rb', line 108

def Complex.generic?(other) # :nodoc:
  other.kind_of?(Integer) or
  other.kind_of?(Float) or
  (defined?(Rational) and other.kind_of?(Rational))
end

.new!(a, b = 0) ⇒ Object

Creates a Complex number a+bi.



124
125
126
# File 'lib/complex.rb', line 124

def Complex.new!(a, b=0)
  new(a,b)
end

.polar(r, theta) ⇒ Object

Creates a Complex number in terms of r (radius) and theta (angle).



117
118
119
# File 'lib/complex.rb', line 117

def Complex.polar(r, theta)
  Complex(r*Math.cos(theta), r*Math.sin(theta))
end

Instance Method Details

#%(other) ⇒ Object

Remainder after division by a real or complex number.



251
252
253
254
255
256
257
258
259
260
# File 'lib/complex.rb', line 251

def % (other)
  if other.kind_of?(Complex)
    Complex(@real % other.real, @image % other.image)
  elsif Complex.generic?(other)
    Complex(@real % other, @image % other)
  else
    x , y = other.coerce(self)
    x % y
  end
end

#*(other) ⇒ Object

Multiplication with real or complex number.



172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/complex.rb', line 172

def * (other)
  if other.kind_of?(Complex)
    re = @real*other.real - @image*other.image
    im = @real*other.image + @image*other.real
    Complex(re, im)
  elsif Complex.generic?(other)
    Complex(@real * other, @image * other)
  else
    x , y = other.coerce(self)
    x * y
  end
end

#**(other) ⇒ Object

Raise this complex number to the given (real or complex) power.



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/complex.rb', line 206

def ** (other)
  if other == 0
    return Complex(1)
  end
  if other.kind_of?(Complex)
    r, theta = polar
    ore = other.real
    oim = other.image
    nr = Math.exp!(ore*Math.log!(r) - oim * theta)
    ntheta = theta*ore + oim*Math.log!(r)
    Complex.polar(nr, ntheta)
  elsif other.kind_of?(Integer)
    if other > 0
	x = self
	z = x
	n = other - 1
	while n != 0
 while (div, mod = n.divmod(2)
 mod == 0)
   x = Complex(x.real*x.real - x.image*x.image, 2*x.real*x.image)
   n = div
 end
 z *= x
 n -= 1
	end
	z
    else
	if defined? Rational
 (Rational(1) / self) ** -other
	else
 self ** Float(other)
	end
    end
  elsif Complex.generic?(other)
    r, theta = polar
    Complex.polar(r**other, theta*other)
  else
    x, y = other.coerce(self)
    x**y
  end
end

#+(other) ⇒ Object

Addition with real or complex number.



140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/complex.rb', line 140

def + (other)
  if other.kind_of?(Complex)
    re = @real + other.real
    im = @image + other.image
    Complex(re, im)
  elsif Complex.generic?(other)
    Complex(@real + other, @image)
  else
    x , y = other.coerce(self)
    x + y
  end
end

#-(other) ⇒ Object

Subtraction with real or complex number.



156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/complex.rb', line 156

def - (other)
  if other.kind_of?(Complex)
    re = @real - other.real
    im = @image - other.image
    Complex(re, im)
  elsif Complex.generic?(other)
    Complex(@real - other, @image)
  else
    x , y = other.coerce(self)
    x - y
  end
end

#/(other) ⇒ Object

Division by real or complex number.



188
189
190
191
192
193
194
195
196
197
# File 'lib/complex.rb', line 188

def / (other)
  if other.kind_of?(Complex)
    self*other.conjugate/other.abs2
  elsif Complex.generic?(other)
    Complex(@real/other, @image/other)
  else
    x, y = other.coerce(self)
    x/y
  end
end

#<=>(other) ⇒ Object

Compares the absolute values of the two numbers.



318
319
320
# File 'lib/complex.rb', line 318

def <=> (other)
  self.abs <=> other.abs
end

#==(other) ⇒ Object

Test for numerical equality (a == a + 0i).



325
326
327
328
329
330
331
332
333
# File 'lib/complex.rb', line 325

def == (other)
  if other.kind_of?(Complex)
    @real == other.real and @image == other.image
  elsif Complex.generic?(other)
    @real == other and @image == 0
  else
    other == self
  end
end

#absObject

Absolute value (aka modulus): distance from the zero point on the complex plane.



281
282
283
# File 'lib/complex.rb', line 281

def abs
  Math.hypot(@real, @image)
end

#abs2Object

Square of the absolute value.



288
289
290
# File 'lib/complex.rb', line 288

def abs2
  @real*@real + @image*@image
end

#argObject Also known as: angle

Argument (angle from (1,0) on the complex plane).



295
296
297
# File 'lib/complex.rb', line 295

def arg
  Math.atan2!(@image, @real)
end

#coerce(other) ⇒ Object

Attempts to coerce other to a Complex number.



338
339
340
341
342
343
344
# File 'lib/complex.rb', line 338

def coerce(other)
  if Complex.generic?(other)
    return Complex.new!(other), self
  else
    super
  end
end

#conjugateObject Also known as: conj

Complex conjugate (z + z.conjugate = 2 * z.real).



310
311
312
# File 'lib/complex.rb', line 310

def conjugate
  Complex(@real, -@image)
end

#denominatorObject

FIXME



349
350
351
# File 'lib/complex.rb', line 349

def denominator
  @real.denominator.lcm(@image.denominator)
end

#hashObject

Returns a hash code for the complex number.



392
393
394
# File 'lib/complex.rb', line 392

def hash
  @real.hash ^ @image.hash
end

#inspectObject

Returns “Complex(real, image)”.



399
400
401
# File 'lib/complex.rb', line 399

def inspect
  sprintf("Complex(%s, %s)", @real.inspect, @image.inspect)
end

#numeratorObject

FIXME



356
357
358
359
360
# File 'lib/complex.rb', line 356

def numerator
  cd = denominator
  Complex(@real.numerator*(cd/@real.denominator),
   @image.numerator*(cd/@image.denominator))
end

#polarObject

Returns the absolute value and the argument.



303
304
305
# File 'lib/complex.rb', line 303

def polar
  return abs, arg
end

#quo(other) ⇒ Object



199
200
201
# File 'lib/complex.rb', line 199

def quo(other)
  Complex(@real.quo(1), @image.quo(1)) / other
end

#to_sObject

Standard string representation of the complex number.



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'lib/complex.rb', line 365

def to_s
  if @real != 0
    if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
	if @image >= 0
 @real.to_s+"+("+@image.to_s+")i"
	else
 @real.to_s+"-("+(-@image).to_s+")i"
	end
    else
	if @image >= 0
 @real.to_s+"+"+@image.to_s+"i"
	else
 @real.to_s+"-"+(-@image).to_s+"i"
	end
    end
  else
    if defined?(Rational) and @image.kind_of?(Rational) and @image.denominator != 1
	"("+@image.to_s+")i"
    else
	@image.to_s+"i"
    end
  end
end