1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
class Complex < Numeric
def initialize(real, imaginary)
real = real.to_f unless real.is_a? Numeric
imaginary = imaginary.to_f unless imaginary.is_a? Numeric
@real = real
@imaginary = imaginary
end
def self.polar(abs, arg = 0)
Complex(abs * Math.cos(arg), abs * Math.sin(arg))
end
def self.rectangular(real, imaginary = 0)
_new(real, imaginary)
end
def inspect
"(#{to_s})"
end
def to_s
"#{real}#{'+' unless imaginary.negative?}#{imaginary}i"
end
def +@
Complex._new(real, imaginary)
end
def -@
Complex._new(-real, -imaginary)
end
def +(rhs)
if rhs.is_a? Complex
Complex._new(real + rhs.real, imaginary + rhs.imaginary)
elsif rhs.is_a? Numeric
Complex._new(real + rhs, imaginary)
end
end
def -(rhs)
if rhs.is_a? Complex
Complex._new(real - rhs.real, imaginary - rhs.imaginary)
elsif rhs.is_a? Numeric
Complex._new(real - rhs, imaginary)
end
end
def *(rhs)
if rhs.is_a? Complex
Complex._new(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary)
elsif rhs.is_a? Numeric
Complex._new(real * rhs, imaginary * rhs)
end
end
def /(rhs)
if rhs.is_a? Complex
div = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary
Complex._new((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div)
elsif rhs.is_a? Numeric
Complex._new(real / rhs, imaginary / rhs)
end
end
alias_method :quo, :/
def ==(rhs)
if rhs.is_a? Complex
real == rhs.real && imaginary == rhs.imaginary
elsif rhs.is_a? Numeric
imaginary.zero? && real == rhs
end
end
def abs
Math.sqrt(abs2)
end
alias_method :magnitude, :abs
def abs2
real * real + imaginary * imaginary
end
def arg
Math.atan2 imaginary, real
end
alias_method :angle, :arg
alias_method :phase, :arg
def conjugate
Complex(real, -imaginary)
end
alias_method :conj, :conjugate
def fdiv(numeric)
Complex(real.to_f / numeric, imaginary.to_f / numeric)
end
def polar
[abs, arg]
end
def real?
false
end
def rectangular
[real, imaginary]
end
alias_method :rect, :rectangular
def to_r
raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero?
Rational(real, 1)
end
alias_method :imag, :imaginary
end
module Kernel
def Complex(real, imaginary = 0)
Complex.rectangular(real, imaginary)
end
end
[Fixnum, Float].each do |cls|
[:+, :-, :*, :/, :==].each do |op|
cls.instance_exec do
original_operator_name = "__original_operator_#{op}_complex"
alias_method original_operator_name, op
define_method op do |rhs|
if rhs.is_a? Complex
Complex(self).send(op, rhs)
else
send(original_operator_name, rhs)
end
end
end
end
end
|