Project

General

Profile

Feature #1316 » test_phasor.rb

peterhil (Peter Hillerström), 03/26/2009 04:58 PM

 
1
# coding: utf-8
2

    
3
require 'test/unit'
4

    
5
### GENERAL UTILITY FUNCTIONS ###
6

    
7
#
8
# Calculate allowable relative error for two floats
9
# See: http://whynotwiki.com/Ruby_/_Numbers
10
#
11
def rel_epsilon(c1,c2)
12
  minerrlimit = 100.0 * Float::MIN
13
  maxabs = [c1.abs, c2.abs].max
14
  rel = maxabs * Float::EPSILON * 25
15
  if rel < minerrlimit 
16
    rel = minerrlimit
17
  end
18
  return rel
19
end
20

    
21
def assert_in_epsilon(c1,c2,message="")
22
  assert_in_delta(c1,c2,rel_epsilon(c1,c2),message)
23
end
24

    
25
def assert_phasor_in_epsilon(c1,c2,message="")
26
  c1_abs, c1_angle = c1.polar
27
  c2_abs, c2_angle = c2.polar
28
  assert_in_delta(c1_abs,c2_abs,rel_epsilon(c1_abs,c2_abs),message)
29
  assert_in_delta(c1_angle,c2_angle,rel_epsilon(c1_angle,c2_angle),message)    
30
end
31

    
32

    
33
### TESTS ###
34

    
35
# Complex tests
36
class TestComplex < Test::Unit::TestCase
37
  require 'complex' unless defined?(Complex)
38

    
39
  def test_complex_coercion
40
    p = Phasor.new(Math.sqrt(2),Math::PI/4)
41
    c = Complex.new(1,1)
42
    assert_block "Couldn't coerce complex into phasor" do
43
      @x, @y = c.coerce(p)
44
    end
45
    assert_kind_of Phasor, @x
46
    assert_kind_of Phasor, @y
47
    assert_equal @x, @y
48
  end
49
  
50
  def test_complex_equals_phasor
51
    p = Phasor.new(Math.sqrt(2),Math::PI/4)
52
    c = Complex.new(1,1)
53
    assert c == p
54
  end
55
  
56
end
57

    
58
class TestPhasor < Test::Unit::TestCase
59
  require '../lib/phasor' unless defined?(Phasor)
60

    
61
  # Numeric tests
62
  def test_numeric_phase
63
    assert_instance_of Phasor, 0.1.phase
64
    assert_equal 5, 5.phase.angle
65
  end
66
  
67
  # Phasor tests
68
  def test_scalar
69
    assert Phasor.scalar?(1)
70
    assert Phasor.scalar?(1.0)
71
    assert Phasor.scalar?(Rational(1,2)) if defined?(Rational)
72
  end
73
  
74
  def test_initialization
75
    p = Phasor.new(1,2)
76
    assert_equal 1, p.abs
77
    assert_equal 2, p.angle
78
    assert_raise TypeError do
79
      Phasor.new(p)
80
    end
81
    assert_instance_of Phasor, Phasor.new(3,4)
82
  end
83

    
84
  def test_aliases
85
    p = Phasor.new(1,2)
86
    assert_equal 1, p.amp
87
    assert_equal 2, p.phase
88
    assert_equal 2, p.arg
89
  end
90
  
91
  def test_coordinate_access
92
    p = Phasor.new(1,Math::PI/4)
93
    assert_in_epsilon Math.sqrt(0.5), p.real
94
    assert_in_epsilon Math.sqrt(0.5), p.imag
95
  end
96
  
97
  def test_conversions
98
    p = Phasor(3,-4)  # Fix angle wrap later
99
    #p = Phasor(3,3)
100
    assert_phasor_in_epsilon(p, p.to_complex.to_phasor)
101
  end
102
  
103
  def test_addition
104
    z1 = Complex(9,3).to_phasor
105
    z2 = Complex(3,7).to_phasor
106
    assert_phasor_in_epsilon(Complex(12,10), (z1+z2).to_complex)
107
    d = Phasor(3,0)
108
    e = Phasor(4,Math::PI/2)
109
    assert_phasor_in_epsilon(Complex(3,4).to_phasor, d+e)
110
    a = Complex(1,2).to_phasor
111
    b = Complex(3,4).to_phasor
112
    assert_phasor_in_epsilon(Complex(4,6), (a+b).to_complex) 
113
    v1 = Phasor(100, 1.0471975511966)   # 60°
114
    v2 = Phasor(130, 2.44346095279206)  # 140°
115
    assert_phasor_in_epsilon(Phasor(177.242355601984, 1.85434312605519), v1+v2) 
116
    assert_phasor_in_epsilon(v1+v2, v2+v1)
117
    z = Complex(1,1)
118
    q = Phasor(1, 0)
119
    assert_nothing_raised(NoMethodError) { a+b+z+q }
120
  end
121
  
122
  def test_scalar_addition
123
    a = Phasor(4,Math::PI/2)
124
    b = 3
125
    assert_phasor_in_epsilon(Complex(3,4).to_phasor, a+b)
126
    c = Complex(6,4).to_phasor
127
    d = -2
128
    assert_phasor_in_epsilon(Complex(4,4).to_phasor, c+d)
129
  end
130
  
131
  def test_substraction
132
    z1 = Complex(9,3).to_phasor
133
    z2 = Complex(3,7).to_phasor
134
    assert_phasor_in_epsilon(Complex(6,-4), (z1-z2).to_complex)
135
    d = Phasor(3,0)
136
    e = Phasor(4,Math::PI/2)
137
    assert_phasor_in_epsilon(Complex(3,-4).to_phasor, d-e)
138
    a = Complex(1,2).to_phasor
139
    b = Complex(3,4).to_phasor
140
    assert_phasor_in_epsilon(Complex(-2.0,-2.0), (a-b).to_complex)
141
    z = Complex(1,1)
142
    q = Phasor(1, 0)
143
    assert_nothing_raised(NoMethodError) { a-b-z-q }
144
  end
145

    
146
  def test_scalar_substraction
147
    a = Phasor(4,Math::PI/2)
148
    b = 3
149
    assert_phasor_in_epsilon(Complex(3,-4).to_phasor, b-a)
150
    c = Complex(6,4).to_phasor
151
    d = -2
152
    assert_phasor_in_epsilon(Complex(8,4).to_phasor, c-d)
153
  end
154

    
155
  def test_multiplication
156
    a = Phasor(1,2)
157
    b = Phasor(3,4)
158
    c = Phasor(3,6)
159
    s = 0.5
160
    r = Rational(1,2) if defined?(Rational)
161
    assert_equal c, a*b
162
    assert_equal a*b, b*a
163
    assert_equal Phasor(0.5, 2), a * s, "Multiplication by scalar failed"
164
    assert_equal Phasor(0.5, 2), a * r, "Multiplication by rational failed" if defined?(Rational)
165
  end
166

    
167
  def test_division
168
    a = Phasor(1,2)
169
    b = Phasor(3,4)
170
    c = Phasor(3,6)
171
    s = 0.5
172
    r = Rational(1,2) if defined?(Rational)
173
    assert_equal a, c/b
174
    assert_equal b, c/a
175
    assert_equal 1, b/b
176
    assert_equal Phasor(2, 2), a / s, "Division by scalar failed"
177
    assert_equal Phasor(2, 2), a / r, "Division by rational failed" if defined?(Rational)
178
  end
179
  
180
  def test_exponentation
181
    x = Phasor(0.5**(1.0/6), Math::PI/6)
182
    w = x**6
183
    assert_phasor_in_epsilon(Phasor(0.5, Math::PI), w)
184
    assert_equal(x, w**(1.0/6))
185
    p = Phasor(3,Math::PI/4)
186
    q = Phasor(4,Math::PI/5)
187
    c = p.to_complex
188
    d = q.to_complex
189
    assert_phasor_in_epsilon (c**d).to_phasor, p**q
190
    z1 = Complex(9,3).to_phasor
191
    z2 = Complex(3,7).to_phasor
192
    assert_phasor_in_epsilon (z1.to_complex ** z2.to_complex).to_phasor, z1 ** z2
193
  end
194

    
195
  def test_modulo
196
    x = Phasor(0.5**(1.0/6), Math::PI/6)
197
    w = x**6
198
  end
199
  
200
  def test_imaginary_number
201
    z = Complex(1,1)
202
    i = Phasor(1, Math::PI/2)
203
    assert_equal Complex::I, Phasor::I
204
    assert_equal Complex(-1,1), i*z
205
  end
206
end
207

    
208

    
209
class TestComplexBasics < Test::Unit::TestCase
210

    
211
   def test_plus_integer
212
     assert_phasor_in_epsilon(Complex(8,7).to_phasor,Complex(3,4).to_phasor + Complex(5,3).to_phasor)
213
     assert_phasor_in_epsilon(Complex(5,1).to_phasor,Complex(4,1).to_phasor + 1)
214
     assert_phasor_in_epsilon(Complex(5,1).to_phasor,1 + Complex(4,1).to_phasor)
215
   end
216

    
217
   def test_minus_integer
218
     assert_phasor_in_epsilon(Complex(2,4).to_phasor, Complex(3,2).to_phasor - Complex(1,-2).to_phasor)
219
     assert_phasor_in_epsilon(Complex(4,5).to_phasor, Complex(5,5).to_phasor - 1)
220
     assert_phasor_in_epsilon(Complex(1,-2).to_phasor, 2 - Complex(1,2).to_phasor)
221
   end
222

    
223
   def test_times_integer
224
     assert_phasor_in_epsilon(Complex(-1,0).to_phasor,Complex(0,1).to_phasor * Complex(0,1).to_phasor)
225
     assert_phasor_in_epsilon(Complex(3,3).to_phasor, Complex(1,1).to_phasor * 3)
226
     assert_phasor_in_epsilon(Complex(4,-2).to_phasor, 2 * Complex(2,-1).to_phasor)
227
   end
228

    
229
   def test_plus_float
230
     assert_phasor_in_epsilon(Complex(1.0,4.0).to_phasor,Complex(2.0,2.0).to_phasor+Complex(-1.0,2.0).to_phasor)
231
   end
232

    
233
   def test_minus_float
234
     assert_phasor_in_epsilon(Complex(3.0,0.0).to_phasor,Complex(2.0,2.0).to_phasor-Complex(-1.0,2.0).to_phasor)
235
   end
236

    
237
   def test_times_float
238
     assert_phasor_in_epsilon(Complex(-2,1).to_phasor,Complex(1,2).to_phasor*Complex(0,1).to_phasor)
239
   end
240

    
241
   def test_division_float
242
     [Complex(1.0,25.0).to_phasor, Complex(8,97).to_phasor, Complex(Float::MAX/2,
243
       Float::MAX/3).to_phasor,
244
     Complex(100.0 / Float::MAX, 200.0 / Float::MAX).to_phasor].each { | c |
245
       assert_phasor_in_epsilon(Complex(1.0,0.0).to_phasor, c / c)
246
     }
247
     assert_phasor_in_epsilon(Complex(-1.0,0.0).to_phasor,Complex(0.0,1.0).to_phasor / Complex(0.0,-1.0).to_phasor)
248
   end
249

    
250
   def test_eps_log
251
     assert_phasor_in_epsilon(Complex(2.0,1.0).to_phasor,Math.log(Math.exp(Complex(2.0,1.0).to_phasor)))
252
   end
253
end
254

    
255
class TestMath < Test::Unit::TestCase
256
  def test_log
257
    p = Phasor(3,Math::PI/6)
258
    assert_equal(Math.log(p.to_complex).to_phasor, Math.flog(p))
259
  end
260

    
261
  def test_exp
262
    p = Phasor(3,0.5)
263
    assert_phasor_in_epsilon(Math.exp(p.to_complex).to_phasor, Math.fexp(p))
264
    assert_phasor_in_epsilon(Math.exp(Complex::I).to_phasor, Math.fexp(Phasor::I))
265
    assert_phasor_in_epsilon(Phasor(1), Math.fexp(2*Math::PI*Phasor::I))
266
  end
267
end