Project

General

Profile

Feature #1316 » test_phasor.rb

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

 
# coding: utf-8

require 'test/unit'

### GENERAL UTILITY FUNCTIONS ###

#
# Calculate allowable relative error for two floats
# See: http://whynotwiki.com/Ruby_/_Numbers
#
def rel_epsilon(c1,c2)
minerrlimit = 100.0 * Float::MIN
maxabs = [c1.abs, c2.abs].max
rel = maxabs * Float::EPSILON * 25
if rel < minerrlimit
rel = minerrlimit
end
return rel
end

def assert_in_epsilon(c1,c2,message="")
assert_in_delta(c1,c2,rel_epsilon(c1,c2),message)
end

def assert_phasor_in_epsilon(c1,c2,message="")
c1_abs, c1_angle = c1.polar
c2_abs, c2_angle = c2.polar
assert_in_delta(c1_abs,c2_abs,rel_epsilon(c1_abs,c2_abs),message)
assert_in_delta(c1_angle,c2_angle,rel_epsilon(c1_angle,c2_angle),message)
end


### TESTS ###

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

def test_complex_coercion
p = Phasor.new(Math.sqrt(2),Math::PI/4)
c = Complex.new(1,1)
assert_block "Couldn't coerce complex into phasor" do
@x, @y = c.coerce(p)
end
assert_kind_of Phasor, @x
assert_kind_of Phasor, @y
assert_equal @x, @y
end
def test_complex_equals_phasor
p = Phasor.new(Math.sqrt(2),Math::PI/4)
c = Complex.new(1,1)
assert c == p
end
end

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

# Numeric tests
def test_numeric_phase
assert_instance_of Phasor, 0.1.phase
assert_equal 5, 5.phase.angle
end
# Phasor tests
def test_scalar
assert Phasor.scalar?(1)
assert Phasor.scalar?(1.0)
assert Phasor.scalar?(Rational(1,2)) if defined?(Rational)
end
def test_initialization
p = Phasor.new(1,2)
assert_equal 1, p.abs
assert_equal 2, p.angle
assert_raise TypeError do
Phasor.new(p)
end
assert_instance_of Phasor, Phasor.new(3,4)
end

def test_aliases
p = Phasor.new(1,2)
assert_equal 1, p.amp
assert_equal 2, p.phase
assert_equal 2, p.arg
end
def test_coordinate_access
p = Phasor.new(1,Math::PI/4)
assert_in_epsilon Math.sqrt(0.5), p.real
assert_in_epsilon Math.sqrt(0.5), p.imag
end
def test_conversions
p = Phasor(3,-4) # Fix angle wrap later
#p = Phasor(3,3)
assert_phasor_in_epsilon(p, p.to_complex.to_phasor)
end
def test_addition
z1 = Complex(9,3).to_phasor
z2 = Complex(3,7).to_phasor
assert_phasor_in_epsilon(Complex(12,10), (z1+z2).to_complex)
d = Phasor(3,0)
e = Phasor(4,Math::PI/2)
assert_phasor_in_epsilon(Complex(3,4).to_phasor, d+e)
a = Complex(1,2).to_phasor
b = Complex(3,4).to_phasor
assert_phasor_in_epsilon(Complex(4,6), (a+b).to_complex)
v1 = Phasor(100, 1.0471975511966) # 60°
v2 = Phasor(130, 2.44346095279206) # 140°
assert_phasor_in_epsilon(Phasor(177.242355601984, 1.85434312605519), v1+v2)
assert_phasor_in_epsilon(v1+v2, v2+v1)
z = Complex(1,1)
q = Phasor(1, 0)
assert_nothing_raised(NoMethodError) { a+b+z+q }
end
def test_scalar_addition
a = Phasor(4,Math::PI/2)
b = 3
assert_phasor_in_epsilon(Complex(3,4).to_phasor, a+b)
c = Complex(6,4).to_phasor
d = -2
assert_phasor_in_epsilon(Complex(4,4).to_phasor, c+d)
end
def test_substraction
z1 = Complex(9,3).to_phasor
z2 = Complex(3,7).to_phasor
assert_phasor_in_epsilon(Complex(6,-4), (z1-z2).to_complex)
d = Phasor(3,0)
e = Phasor(4,Math::PI/2)
assert_phasor_in_epsilon(Complex(3,-4).to_phasor, d-e)
a = Complex(1,2).to_phasor
b = Complex(3,4).to_phasor
assert_phasor_in_epsilon(Complex(-2.0,-2.0), (a-b).to_complex)
z = Complex(1,1)
q = Phasor(1, 0)
assert_nothing_raised(NoMethodError) { a-b-z-q }
end

def test_scalar_substraction
a = Phasor(4,Math::PI/2)
b = 3
assert_phasor_in_epsilon(Complex(3,-4).to_phasor, b-a)
c = Complex(6,4).to_phasor
d = -2
assert_phasor_in_epsilon(Complex(8,4).to_phasor, c-d)
end

def test_multiplication
a = Phasor(1,2)
b = Phasor(3,4)
c = Phasor(3,6)
s = 0.5
r = Rational(1,2) if defined?(Rational)
assert_equal c, a*b
assert_equal a*b, b*a
assert_equal Phasor(0.5, 2), a * s, "Multiplication by scalar failed"
assert_equal Phasor(0.5, 2), a * r, "Multiplication by rational failed" if defined?(Rational)
end

def test_division
a = Phasor(1,2)
b = Phasor(3,4)
c = Phasor(3,6)
s = 0.5
r = Rational(1,2) if defined?(Rational)
assert_equal a, c/b
assert_equal b, c/a
assert_equal 1, b/b
assert_equal Phasor(2, 2), a / s, "Division by scalar failed"
assert_equal Phasor(2, 2), a / r, "Division by rational failed" if defined?(Rational)
end
def test_exponentation
x = Phasor(0.5**(1.0/6), Math::PI/6)
w = x**6
assert_phasor_in_epsilon(Phasor(0.5, Math::PI), w)
assert_equal(x, w**(1.0/6))
p = Phasor(3,Math::PI/4)
q = Phasor(4,Math::PI/5)
c = p.to_complex
d = q.to_complex
assert_phasor_in_epsilon (c**d).to_phasor, p**q
z1 = Complex(9,3).to_phasor
z2 = Complex(3,7).to_phasor
assert_phasor_in_epsilon (z1.to_complex ** z2.to_complex).to_phasor, z1 ** z2
end

def test_modulo
x = Phasor(0.5**(1.0/6), Math::PI/6)
w = x**6
end
def test_imaginary_number
z = Complex(1,1)
i = Phasor(1, Math::PI/2)
assert_equal Complex::I, Phasor::I
assert_equal Complex(-1,1), i*z
end
end


class TestComplexBasics < Test::Unit::TestCase

def test_plus_integer
assert_phasor_in_epsilon(Complex(8,7).to_phasor,Complex(3,4).to_phasor + Complex(5,3).to_phasor)
assert_phasor_in_epsilon(Complex(5,1).to_phasor,Complex(4,1).to_phasor + 1)
assert_phasor_in_epsilon(Complex(5,1).to_phasor,1 + Complex(4,1).to_phasor)
end

def test_minus_integer
assert_phasor_in_epsilon(Complex(2,4).to_phasor, Complex(3,2).to_phasor - Complex(1,-2).to_phasor)
assert_phasor_in_epsilon(Complex(4,5).to_phasor, Complex(5,5).to_phasor - 1)
assert_phasor_in_epsilon(Complex(1,-2).to_phasor, 2 - Complex(1,2).to_phasor)
end

def test_times_integer
assert_phasor_in_epsilon(Complex(-1,0).to_phasor,Complex(0,1).to_phasor * Complex(0,1).to_phasor)
assert_phasor_in_epsilon(Complex(3,3).to_phasor, Complex(1,1).to_phasor * 3)
assert_phasor_in_epsilon(Complex(4,-2).to_phasor, 2 * Complex(2,-1).to_phasor)
end

def test_plus_float
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)
end

def test_minus_float
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)
end

def test_times_float
assert_phasor_in_epsilon(Complex(-2,1).to_phasor,Complex(1,2).to_phasor*Complex(0,1).to_phasor)
end

def test_division_float
[Complex(1.0,25.0).to_phasor, Complex(8,97).to_phasor, Complex(Float::MAX/2,
Float::MAX/3).to_phasor,
Complex(100.0 / Float::MAX, 200.0 / Float::MAX).to_phasor].each { | c |
assert_phasor_in_epsilon(Complex(1.0,0.0).to_phasor, c / c)
}
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)
end

def test_eps_log
assert_phasor_in_epsilon(Complex(2.0,1.0).to_phasor,Math.log(Math.exp(Complex(2.0,1.0).to_phasor)))
end
end

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

def test_exp
p = Phasor(3,0.5)
assert_phasor_in_epsilon(Math.exp(p.to_complex).to_phasor, Math.fexp(p))
assert_phasor_in_epsilon(Math.exp(Complex::I).to_phasor, Math.fexp(Phasor::I))
assert_phasor_in_epsilon(Phasor(1), Math.fexp(2*Math::PI*Phasor::I))
end
end
(2-2/2)