1

# coding: utf8

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), (z1z2).to_complex)

135

d = Phasor(3,0)

136

e = Phasor(4,Math::PI/2)

137

assert_phasor_in_epsilon(Complex(3,4).to_phasor, de)

138

a = Complex(1,2).to_phasor

139

b = Complex(3,4).to_phasor

140

assert_phasor_in_epsilon(Complex(2.0,2.0), (ab).to_complex)

141

z = Complex(1,1)

142

q = Phasor(1, 0)

143

assert_nothing_raised(NoMethodError) { abzq }

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, ba)

150

c = Complex(6,4).to_phasor

151

d = 2

152

assert_phasor_in_epsilon(Complex(8,4).to_phasor, cd)

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_phasorComplex(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
