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.



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

def image
  @image
end

#realObject (readonly)

The real part of a complex number.



406
407
408
# File 'lib/complex.rb', line 406

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.



247
248
249
250
251
252
253
254
255
256
# File 'lib/complex.rb', line 247

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.



202
203
204
205
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
# File 'lib/complex.rb', line 202

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.



314
315
316
# File 'lib/complex.rb', line 314

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

#==(other) ⇒ Object

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



321
322
323
324
325
326
327
328
329
# File 'lib/complex.rb', line 321

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.



277
278
279
# File 'lib/complex.rb', line 277

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

#abs2Object

Square of the absolute value.



284
285
286
# File 'lib/complex.rb', line 284

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

#argObject Also known as: angle

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



291
292
293
# File 'lib/complex.rb', line 291

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

#coerce(other) ⇒ Object

Attempts to coerce other to a Complex number.



334
335
336
337
338
339
340
# File 'lib/complex.rb', line 334

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).



306
307
308
# File 'lib/complex.rb', line 306

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

#denominatorObject

FIXME



345
346
347
# File 'lib/complex.rb', line 345

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

#hashObject

Returns a hash code for the complex number.



388
389
390
# File 'lib/complex.rb', line 388

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

#inspectObject

Returns "Complex(real, image)".



395
396
397
# File 'lib/complex.rb', line 395

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

#numeratorObject

FIXME



352
353
354
355
356
# File 'lib/complex.rb', line 352

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

#polarObject

Returns the absolute value and the argument.



299
300
301
# File 'lib/complex.rb', line 299

def polar
  return abs, arg
end

#to_sObject

Standard string representation of the complex number.



361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
# File 'lib/complex.rb', line 361

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