glmath 0.0.1.dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,81 @@
1
+ module GLMath
2
+ class Matrix2
3
+
4
+ class << self
5
+ def dimension
6
+ 2
7
+ end
8
+
9
+ #conter-clockwise rotation
10
+ def rotation(theta, homogenous = false)
11
+ s, c = Math.sin(theta), Math.cos(theta)
12
+ m = new(c, -s, s, c)
13
+ homogenous ? m.expand : m
14
+ end
15
+
16
+ def scale(x, y, homogenous = false)
17
+ m = diagonal(x, y)
18
+ homogenous ? m.expand : m
19
+ end
20
+ end
21
+
22
+ include Matrix
23
+
24
+ def *(v)
25
+ case v
26
+ when Vector2
27
+ v.class.new(@m[0] * v.x + @m[1] * v.y, @m[2] * v.x + @m[3] * v.y)
28
+ when Matrix2
29
+ m = v.instance_variable_get(:@m)
30
+ self.class.new(@m[0]*m[0] + @m[1]*m[2], @m[0]*m[1] + @m[1]*m[3],
31
+ @m[2]*m[0] + @m[3]*m[2], @m[2]*m[1] + @m[3]*m[3])
32
+ when Numeric
33
+ super
34
+ else
35
+ raise ArgumentError
36
+ end
37
+ end
38
+
39
+ def adjugate!
40
+ @m = [ @m[3], -@m[1],
41
+ -@m[2], @m[0]]
42
+ self
43
+ end
44
+
45
+ def determinant
46
+ @m[0] * @m[3] - @m[1] * @m[2]
47
+ end
48
+
49
+ def expand
50
+ Matrix3.new(@m[0], @m[1], 0.0,
51
+ @m[2], @m[3], 0.0,
52
+ 0.0, 0.0, 1.0)
53
+ end
54
+
55
+ def inverse
56
+ d = determinant
57
+ raise ArgumentError, 'Determinant is zero' if d.zero?
58
+ adjugate * (1.0 / d)
59
+ end
60
+
61
+ def lup
62
+ raise ArgumentError, "Determinant is zero" if singular?
63
+
64
+ if @m[0].abs > @m[1].abs
65
+ a, b, c, d = 0, 1, 2, 3
66
+ p = self.class.new(1.0, 0.0, 0.0, 1.0)
67
+ else
68
+ a, b, c, d = 2, 3, 0, 1
69
+ p = self.class.new(0.0, 1.0, 1.0, 0.0)
70
+ end
71
+
72
+ l = self.class.new(1.0, 0.0, @m[c] / @m[a], 1.0)
73
+ u = self.class.new(@m[a], @m[b], 0.0, @m[d] - @m[b]*@m[c] / @m[a])
74
+ [l, u, p]
75
+ end
76
+
77
+ alias_method :det, :determinant
78
+ alias_method :lup_decomposition, :lup
79
+
80
+ end
81
+ end
@@ -0,0 +1,108 @@
1
+ module GLMath
2
+ class Matrix3
3
+
4
+ class << self
5
+ def dimension
6
+ 3
7
+ end
8
+
9
+ def rotation(angle, axis, homogenous = false)
10
+ n = axis.normalize
11
+ ct = Math.cos(angle)
12
+ st = Math.sin(angle)
13
+ ct1 = 1 - ct
14
+ xy = n.x * n.y * ct1
15
+ xz = n.x * n.z * ct1
16
+ yz = n.y * n.z * ct1
17
+
18
+ m = new(n.x*n.x*ct1 + ct, xy + n.z * st, xz - n.y * st,
19
+ xy - n.z * st, n.y*n.y*ct1 + ct, yz + n.x * st,
20
+ xz + n.y * st, yz - n.x * st, n.z*n.z*ct1 + ct)
21
+ homogenous ? m.expand : m
22
+ end
23
+
24
+ def scale(x, y, z, homogenous = false)
25
+ m = diagonal(x, y, z)
26
+ homogenous ? m.expand : m
27
+ end
28
+
29
+ def translation(x, y)
30
+ Matrix3.new(1.0, 0.0, 0.0,
31
+ 0.0, 1.0, 0.0,
32
+ x, y, 1.0)
33
+ end
34
+
35
+ def from_euler_angle(x:, y:, z:)
36
+ # TODO
37
+ end
38
+ end
39
+
40
+ include Matrix
41
+
42
+ def *(v)
43
+ case v
44
+ when Vector3
45
+ v.class.new(@m[0] * v.x + @m[1] * v.y + @m[2] * v.z,
46
+ @m[3] * v.x + @m[4] * v.y + @m[5] * v.z,
47
+ @m[6] * v.x + @m[7] * v.y + @m[8] * v.z)
48
+ when Matrix3
49
+ m = v.instance_variable_get(:@m)
50
+ self.class.new(
51
+ @m[0]*m[0]+@m[1]*m[3]+@m[2]*m[6], @m[0]*m[1]+@m[1]*m[4]+@m[2]*m[7], @m[0]*m[2] + @m[1]*m[5] + @m[2]*m[8],
52
+ @m[3]*m[0]+@m[4]*m[3]+@m[5]*m[6], @m[3]*m[1]+@m[4]*m[4]+@m[5]*m[7], @m[3]*m[2] + @m[4]*m[5] + @m[5]*m[8],
53
+ @m[6]*m[0]+@m[7]*m[3]+@m[8]*m[6], @m[6]*m[1]+@m[7]*m[4]+@m[8]*m[7], @m[6]*m[2] + @m[7]*m[5] + @m[8]*m[8])
54
+ else
55
+ super
56
+ end
57
+ end
58
+
59
+ def adjugate!
60
+ @m =[@m[4] * @m[8] - @m[5] * @m[7],
61
+ @m[5] * @m[6] - @m[3] * @m[8],
62
+ @m[3] * @m[7] - @m[4] * @m[6],
63
+ @m[2] * @m[7] - @m[1] * @m[8],
64
+ @m[0] * @m[8] - @m[2] * @m[6],
65
+ @m[1] * @m[6] - @m[0] * @m[7],
66
+ @m[1] * @m[5] - @m[2] * @m[4],
67
+ @m[2] * @m[3] - @m[0] * @m[5],
68
+ @m[0] * @m[4] - @m[1] * @m[3]]
69
+ self
70
+ end
71
+
72
+ def determinant
73
+ @m[0] * ( @m[4] * @m[8] - @m[5] * @m[7] ) +
74
+ @m[1] * ( @m[5] * @m[6] - @m[3] * @m[8] ) +
75
+ @m[2] * ( @m[3] * @m[7] - @m[4] * @m[6] )
76
+ end
77
+
78
+ def expand
79
+ Matrix4.new(@m[0], @m[1], @m[2], 0.0,
80
+ @m[3], @m[4], @m[5], 0.0,
81
+ @m[6], @m[7], @m[8], 0.0,
82
+ 0.0, 0.0, 0.0, 1.0)
83
+ end
84
+
85
+ def to_axis_angle
86
+ # TODO
87
+ end
88
+
89
+ def orthonormalize
90
+ # TODO
91
+ end
92
+
93
+ def eigen_decomposition()
94
+ # TODO
95
+ end
96
+
97
+ def to_euler_angle
98
+ # TODO
99
+ end
100
+
101
+ def slerp
102
+ # TODO
103
+ end
104
+
105
+ alias_method :det, :determinant
106
+
107
+ end
108
+ end
@@ -0,0 +1,145 @@
1
+ module GLMath
2
+ # Left Handed
3
+ class Matrix4
4
+ class << self
5
+ def dimension
6
+ 4
7
+ end
8
+
9
+ def look_at(eye, center, up)
10
+ f = (center - eye).normalize!
11
+ s = f.cross(up).normalize!
12
+ u = s.cross(f).normalize!
13
+ new(s.x, u.x, -f.x, 0.0,
14
+ s.y, u.y, -f.y, 0.0,
15
+ s.z, u.z, -f.z, 0.0,
16
+ -eye.x, -eye.y, -eye.z, 1.0)
17
+ end
18
+
19
+ def ortho(left, right, bottom, top, near, far)
20
+ rl = right.to_f - left.to_f
21
+ tb = top.to_f - bottom.to_f
22
+ fn = far.to_f - near.to_f
23
+
24
+ new(2.0/rl, 0.0, 0.0, 0.0,
25
+ 0.0, 2.0/tb, 0.0, 0.0,
26
+ 0.0, 0.0, -2.0/fn, 0.0,
27
+ -(right + left)/rl, -(top + bottom)/tb, -(far + near)/fn, 1.0)
28
+ end
29
+
30
+ def perspective(fovy, aspect, near, far)
31
+ zoom = 1.0 / Math.tan(fovy * 0.5)
32
+ fn = 1.0 / (far - near)
33
+ new(zoom/aspect, 0.0, 0.0, 0.0,
34
+ 0.0, zoom, 0.0, 0.0,
35
+ 0.0, 0.0, (far + near)*fn, 1.0,
36
+ 0.0, 0.0, -2.0*far*near*fn, 0.0)
37
+ end
38
+
39
+ def rotation(angle, axis)
40
+ Matrix3.rotation(angle, axis, true)
41
+ end
42
+
43
+ def scale(x, y, z, w = 1.0)
44
+ diagonal(x, y, z, w)
45
+ end
46
+
47
+ def translation(x, y, z)
48
+ Matrix4.new(1.0, 0.0, 0.0, 0.0,
49
+ 0.0, 1.0, 0.0, 0.0,
50
+ 0.0, 0.0, 1.0, 0.0,
51
+ x, y, z, 1.0)
52
+ end
53
+ end
54
+
55
+ include Matrix
56
+
57
+ def *(v)
58
+ case v
59
+ when Vector4
60
+ v.class.new(
61
+ @m[ 0] * v.x + @m[ 1] * v.y + @m[ 2] * v.z + @m[ 3] * v.w,
62
+ @m[ 4] * v.x + @m[ 5] * v.y + @m[ 6] * v.z + @m[ 7] * v.w,
63
+ @m[ 8] * v.x + @m[ 9] * v.y + @m[10] * v.z + @m[11] * v.w,
64
+ @m[12] * v.x + @m[13] * v.y + @m[14] * v.z + @m[15] * v.w)
65
+ when Matrix4
66
+ m = v.instance_variable_get(:@m)
67
+ self.class.new(
68
+ @m[ 0] * m[0] + @m[ 1] * m[4] + @m[ 2] * m[ 8] + @m[ 3] * m[12],
69
+ @m[ 0] * m[1] + @m[ 1] * m[5] + @m[ 2] * m[ 9] + @m[ 3] * m[13],
70
+ @m[ 0] * m[2] + @m[ 1] * m[6] + @m[ 2] * m[10] + @m[ 3] * m[14],
71
+ @m[ 0] * m[3] + @m[ 1] * m[7] + @m[ 2] * m[11] + @m[ 3] * m[15],
72
+ @m[ 4] * m[0] + @m[ 5] * m[4] + @m[ 6] * m[ 8] + @m[ 7] * m[12],
73
+ @m[ 4] * m[1] + @m[ 5] * m[5] + @m[ 6] * m[ 9] + @m[ 7] * m[13],
74
+ @m[ 4] * m[2] + @m[ 5] * m[6] + @m[ 6] * m[10] + @m[ 7] * m[14],
75
+ @m[ 4] * m[3] + @m[ 5] * m[7] + @m[ 6] * m[11] + @m[ 7] * m[15],
76
+ @m[ 8] * m[0] + @m[ 9] * m[4] + @m[10] * m[ 8] + @m[11] * m[12],
77
+ @m[ 8] * m[1] + @m[ 9] * m[5] + @m[10] * m[ 9] + @m[11] * m[13],
78
+ @m[ 8] * m[2] + @m[ 9] * m[6] + @m[10] * m[10] + @m[11] * m[14],
79
+ @m[ 8] * m[3] + @m[ 9] * m[7] + @m[10] * m[11] + @m[11] * m[15],
80
+ @m[12] * m[0] + @m[13] * m[4] + @m[14] * m[ 8] + @m[15] * m[12],
81
+ @m[12] * m[1] + @m[13] * m[5] + @m[14] * m[ 9] + @m[15] * m[13],
82
+ @m[12] * m[2] + @m[13] * m[6] + @m[14] * m[10] + @m[15] * m[14],
83
+ @m[12] * m[3] + @m[13] * m[7] + @m[14] * m[11] + @m[15] * m[15])
84
+ else
85
+ super
86
+ end
87
+ end
88
+
89
+ def adjoint!
90
+ a = @m[4] * @m[9] - @m[5] * @m[8]
91
+ b = @m[4] * @m[10] - @m[6] * @m[8]
92
+ c = @m[4] * @m[11] - @m[7] * @m[8]
93
+ d = @m[4] * @m[13] - @m[5] * @m[12]
94
+ f = @m[4] * @m[14] - @m[6] * @m[12]
95
+ g = @m[4] * @m[15] - @m[7] * @m[12]
96
+ h = @m[5] * @m[10] - @m[6] * @m[9]
97
+ i = @m[5] * @m[11] - @m[7] * @m[9]
98
+ j = @m[5] * @m[14] - @m[6] * @m[13]
99
+ k = @m[5] * @m[15] - @m[7] * @m[13]
100
+ l = @m[6] * @m[11] - @m[7] * @m[10]
101
+ m = @m[6] * @m[15] - @m[7] * @m[14]
102
+ n = @m[8] * @m[13] - @m[9] * @m[12]
103
+ o = @m[8] * @m[14] - @m[10] * @m[12]
104
+ p = @m[8] * @m[15] - @m[11] * @m[12]
105
+ q = @m[9] * @m[14] - @m[10] * @m[13]
106
+ r = @m[9] * @m[15] - @m[11] * @m[13]
107
+ s = @m[10] * @m[15] - @m[11] * @m[14]
108
+
109
+ @m = [+ @m[5] * s - @m[6] * r + @m[7] * q,
110
+ - @m[4] * s + @m[6] * p - @m[7] * o,
111
+ + @m[4] * r - @m[5] * p + @m[7] * n,
112
+ - @m[4] * q + @m[5] * o - @m[6] * n,
113
+ - @m[1] * s + @m[2] * r - @m[3] * q,
114
+ + @m[0] * s - @m[2] * p + @m[3] * o,
115
+ - @m[0] * r + @m[1] * p - @m[3] * n,
116
+ + @m[0] * q - @m[1] * o + @m[2] * n,
117
+ + @m[1] * m - @m[2] * k + @m[3] * j,
118
+ - @m[0] * m + @m[2] * g - @m[3] * f,
119
+ + @m[0] * k - @m[1] * g + @m[3] * d,
120
+ - @m[0] * j + @m[1] * f - @m[2] * d,
121
+ - @m[1] * l + @m[2] * i - @m[3] * h,
122
+ + @m[0] * l - @m[2] * c + @m[3] * b,
123
+ - @m[0] * i + @m[1] * c - @m[3] * a,
124
+ + @m[0] * h - @m[1] * b + @m[2] * a]
125
+ self
126
+ end
127
+
128
+ def determinant
129
+ a = @m[10] * @m[15] - @m[11] * @m[14]
130
+ b = @m[11] * @m[13] - @m[9] * @m[15]
131
+ c = @m[9] * @m[14] - @m[10] * @m[13]
132
+ d = @m[8] * @m[15] - @m[11] * @m[12]
133
+ e = @m[10] * @m[12] - @m[8] * @m[14]
134
+ f = @m[8] * @m[13] - @m[9] * @m[12]
135
+
136
+ @m[0] * ( @m[5] * a + @m[6] * b + @m[7] * c) +
137
+ @m[1] * (-@m[4] * a + @m[6] * d + @m[7] * e) +
138
+ @m[2] * (-@m[4] * b - @m[5] * d + @m[7] * f) +
139
+ @m[3] * (-@m[4] * c - @m[5] * e - @m[6] * f)
140
+ end
141
+
142
+ alias_method :det, :determinant
143
+
144
+ end
145
+ end
@@ -0,0 +1,91 @@
1
+ module GLMath
2
+ class MatrixStack
3
+
4
+ def initialize
5
+ @stack = [Matrix4.I]
6
+ end
7
+
8
+ %w'* - +'.each do |m|
9
+ define_method(m, ->(v) do
10
+ @stack[-1] = @stack.last.send(m, check(v))
11
+ self
12
+ end)
13
+ end
14
+
15
+ def <<(m)
16
+ @stack << check(m)
17
+ self
18
+ end
19
+
20
+ def current
21
+ @stack.last.dup
22
+ end
23
+
24
+ def dup
25
+ MatrixStack.new.tap { |ms| ms.instance_variable_set(:@stack, @stack.map(&:dup)) }
26
+ end
27
+
28
+ def push(m = current)
29
+ self << m
30
+ return self unless block_given?
31
+ yield self
32
+ pop
33
+ self
34
+ end
35
+
36
+ def pop(n = 1)
37
+ @stack.pop(n)
38
+ end
39
+
40
+ def load(*args)
41
+ @stack[-1] = case
42
+ when args.length == 16 then Matrix4[*args]
43
+ when args.length == 9 then Matrix3[*args].expand
44
+ when args.length == 1 then check(args[0])
45
+ else raise ArgumentError
46
+ end
47
+ end
48
+
49
+ def load_identity
50
+ load(Matrix4.I)
51
+ end
52
+
53
+ def look_at(eye, center, up)
54
+ self * Matrix4.look_at(eye, center, up)
55
+ end
56
+
57
+ def ortho(left, right, bottom, top, near, far)
58
+ self * Matrix4.ortho(left, right, bottom, top, near, far)
59
+ end
60
+
61
+ def perspective(fovy, aspect, near, far)
62
+ self * Matrix4.perspective(fovy, aspect, near, far)
63
+ end
64
+
65
+ def rotate(arg, axis = nil)
66
+ self * case axis
67
+ when Vector3, Vector4 then Matrix4.rotation(arg, axis)
68
+ when Quaternion, EulerAngle then arg.to_matrix
69
+ else raise ArgumentError
70
+ end
71
+ end
72
+
73
+ def scale(x, y, z, w = 1.0)
74
+ self * Matrix4.scale(x, y, z, w)
75
+ end
76
+
77
+ #def shear()
78
+ # #TODO
79
+ #end
80
+
81
+ def translate(x, y, z)
82
+ self * Matrix4.translation(x, y, z)
83
+ end
84
+
85
+ private
86
+ def check(m)
87
+ raise ArgumentError unless m.is_a?(Matrix4)
88
+ m
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,212 @@
1
+ module GLMath
2
+ class Quaternion
3
+ class << self
4
+ def [](*args)
5
+ new(*args)
6
+ end
7
+
8
+ def from_angle_axis(angle, axis)
9
+ angle *= 0.5
10
+ axis = axis.normalize
11
+ sa = Math.sin(angle)
12
+ new(Math.cos(angle), sa * axis.x, sa * axis.y, sa * axis.z)
13
+ end
14
+
15
+ def identity
16
+ new(1.0, 0.0, 0.0, 0.0)
17
+ end
18
+
19
+ def slerp(q0, q1, t)
20
+ (q1 * q0.inverse).power(t) * q0
21
+ end
22
+
23
+ alias_method :I, :identity
24
+ end
25
+
26
+ def initialize(w, x, y, z)
27
+ @q = w, x, y, z
28
+ raise ArgumentError, 'arguments must be Numeric' unless @q.all? { |e| e.is_a?(Numeric) }
29
+ end
30
+
31
+ def +(v)
32
+ case v
33
+ when Numeric
34
+ self.class.new(v + w, x, y, z)
35
+ when Quaternion
36
+ self.class.new(q + v.w, x + v.x, y + v.y, z + v.z)
37
+ else
38
+ v + self
39
+ end
40
+ end
41
+
42
+ def -(q)
43
+ self + (-q)
44
+ end
45
+
46
+ def *(v)
47
+ case v
48
+ when Numeric
49
+ self.class.new(q * v, x * v, y * v, z * v)
50
+ when Quaternion
51
+ cross_product(v)
52
+ end
53
+ end
54
+
55
+ def /(v)
56
+ case v
57
+ when Numeric
58
+ self.class.new(*@q.map { |i| i/v})
59
+ when Quaternion
60
+ self * v.inverse
61
+ end
62
+ end
63
+
64
+ def -@
65
+ self.class.new(*@q.map(&:-@))
66
+ end
67
+
68
+ def ==(other)
69
+ self.class === other && @q == other.instance_variable_get(:@q)
70
+ end
71
+
72
+ %w'w x y z'.each_with_index do |m, i|
73
+ define_method m, ->() { @q[i] }
74
+ define_method "#{m}=", ->(v) { @q[i] = v }
75
+ end
76
+
77
+ def coerce(v)
78
+ case v
79
+ when Numeric then return Scalar.new(v), self
80
+ else raise TypeError, "#{self.class} can't be coerced into #{v.class}"
81
+ end
82
+ end
83
+
84
+ def conjugate
85
+ self.class.new(w, -x, -y, -z)
86
+ end
87
+
88
+ def conjugate!
89
+ @q = w, -x, -y, -z
90
+ self
91
+ end
92
+
93
+ #Warning: standard notation.
94
+ def cross_product(q)
95
+ self.class.new(
96
+ w * q.w - x * q.x - y * q.y - z * q.z,
97
+ w * q.x + x * q.w + y * q.z - z * q.y,
98
+ w * q.y - x * q.z + y * q.w + z * q.x,
99
+ w * q.z + x * q.y - y * q.x + z * q.w)
100
+ end
101
+
102
+ def difference(q)
103
+ q * inverse
104
+ end
105
+
106
+ def dot_product(q)
107
+ w * q.w + x * q.x + y * q.y + z * q.z
108
+ end
109
+
110
+ def dup
111
+ self.class.new(*@q)
112
+ end
113
+
114
+ def exp
115
+ a = Math.sqrt(x*x + y*y + z*z)
116
+ ew = Math.exp(w)
117
+ s = ew * Math.sin(a) / a
118
+ self.class.new(ew * Math.cos(a), x * s, y * s, z * s)
119
+ end
120
+
121
+ def imaginary
122
+ [x, y, z]
123
+ end
124
+
125
+ def inspect
126
+ "Quaternion[#{w}, #{x}, #{y}, #{z}]"
127
+ end
128
+
129
+ def inverse
130
+ conjugate / norm
131
+ end
132
+
133
+ def log
134
+ nv = x*x + y*y + z*z
135
+ nq = Math.sqrt(w*w + nv)
136
+ s = Math.acos(w/nq) / Math.sqrt(nv)
137
+ self.class.new(Math.log(nq), x * s, y * s, z * s)
138
+ end
139
+
140
+ def norm
141
+ Math.sqrt(squared_norm)
142
+ end
143
+
144
+ def normalize
145
+ self / norm
146
+ end
147
+
148
+ def normalize!
149
+ i = 1.0 / norm
150
+ @q.map! { |e| e * i }
151
+ self
152
+ end
153
+
154
+ def power(p)
155
+ (log*p).exp
156
+ end
157
+
158
+ def real
159
+ w
160
+ end
161
+
162
+ def rotate(v3)
163
+ Vector3[*(self * Quaternion[0.0, *v3] * inverse).to_a[1..-1]]
164
+ end
165
+
166
+ def squared_norm
167
+ w * w + x * x + y * y + z * z
168
+ end
169
+
170
+ def to_a
171
+ @q.dup
172
+ end
173
+
174
+ def to_s(notation = nil)
175
+ case notation
176
+ when :scalar_vector
177
+ "(#{w}, [#{x}, #{y}, #{z}])"
178
+ when :vertical
179
+ "w=#{w}\nx=#{x}\ny=#{y}\nz=#{z}"
180
+ when :angle_axis
181
+ else
182
+ "Quaternion[w=#{w}, x=#{x}, y=#{y}, z=#{z}]"
183
+ end
184
+ end
185
+
186
+ def to_matrix
187
+ xx = 2 * x * x
188
+ yy = 2 * y * y
189
+ zz = 2 * z * z
190
+ xy = 2 * x * y
191
+ wz = 2 * w * z
192
+ xz = 2 * x * z
193
+ wy = 2 * w * y
194
+ yz = 2 * y * z
195
+ wx = 2 * w * x
196
+
197
+ Matrix4[1 - yy - zz, xy - wz, xz + wy, 0,
198
+ xy + wz, 1 - xx - zz, yz - wx, 0,
199
+ xz - wy, yz + wx, 1 - xx - yy, 0,
200
+ 0, 0, 0, 1]
201
+ end
202
+
203
+ alias_method :conj, :conjugate
204
+ alias_method :conj!, :conjugate
205
+ alias_method :cross, :cross_product
206
+ alias_method :dot, :dot_product
207
+ alias_method :im, :imaginary
208
+ alias_method :imag, :imaginary
209
+ alias_method :inv, :inverse
210
+ alias_method :re, :real
211
+ end
212
+ end