| Class | AppMath::Vec |
| In: |
linalg.rb
|
| Parent: | Object |
Vector space of arbitrary dimension. The intended usage is that the components of a vector are all either real or complex. Since
x = Vec.new(anyArray); x[1] = anyObject
works, there is no guaranty for type-uniformity of the components of a vector.
| x | [RW] |
These are the 3 mehods to generate a vector via ‘new‘
a = Vec.new(anArray) b = Vec.new(aVec) c = Vec.new(aPositiveInteger, aRealOrComplex)
# File linalg.rb, line 42
42: def initialize(*arg)
43: case arg.size
44: when 1
45: a0 = arg[0]
46: if a0.is_a?(Array)
47: @x = Array.new(a0)
48: elsif a0.is_a?(Vec)
49: @x = Array.new(a0.x)
50: else
51: fail "object can't be used to build a vector"
52: end
53: when 2
54: n = arg[0]
55: fail "first argument has to be an integer" unless n.integer?
56: fail "first argument must be non-negative" unless n >= 0
57: @x = Array.new(n,arg[1])
58: end
59: end
Consistency test of class Vec.
# File linalg.rb, line 289
289: def Vec.test(n0, verbose = true , complex = false)
290: puts "Doing Vec.test( n = #{n0}, verbose = #{verbose}, " +
291: "complex = #{complex}) for R.prec = #{R.prec}:"
292: puts "*************************************************"
293:
294: t1 = Time.now
295: s = R.c0
296: puts "class of s is " + s.class.to_s
297: i = n0
298: a = Vec.tob(n0, i, complex)
299: i += 1
300: b = Vec.tob(n0, i, complex)
301: i += 1
302: c = Vec.tob(n0, i, complex)
303: i += 1
304: s1 = complex ? C.ran(i) : R.ran(i)
305: i += 1
306: s2 = complex ? C.ran(i) : R.ran(i)
307:
308: r = (a + b) + c
309: l = a + (b + c)
310: ds = r.dis(l)
311: puts "associativity: ds = " + ds.to_s if verbose
312: s += ds
313:
314: r = (a - b) + c
315: l = a - (b - c)
316: ds = r.dis(l)
317: puts "associativity 2: ds = " + ds.to_s if verbose
318: s += ds
319:
320: r = (a + b) * s1
321: l = a * s1 + b * s1
322: ds = r.dis(l)
323: puts "distributivity: ds = " + ds.to_s if verbose
324: s += ds
325:
326: r = c * (s1*s2)
327: l = (c * s1) * s2
328: ds = r.dis(l)
329: puts "distributivity of multiplication by scalars: ds = " + ds.to_s if verbose
330: s += ds
331:
332: r = a
333: l = -(-a)
334: ds = r.dis(l)
335: puts "idempotency of unary minus: ds = " + ds.to_s if verbose
336: s += ds
337:
338: r = (a + b).spr(c)
339: l = a.spr(c) + b.spr(c)
340: ds = r.dis(l)
341: puts "distributivity of spr: ds = " + ds.to_s if verbose
342: s += ds
343:
344: t2 = Time.now
345:
346: if verbose
347: puts
348: a.prn("a")
349: puts
350: b.prn("b")
351: puts
352: c.prn("c")
353: puts
354: s1.prn("s1")
355: puts
356: s2.prn("s2")
357: end
358:
359: puts "class of s is " + s.class.to_s + " ."
360: puts "The error sum s is " + s.to_s + " ."
361: puts "It should be close to 0."
362: puts "Computation time was " + (t2-t1).to_s
363: s
364: end
Test object.
Returns a Vec res such that res.dim == n. Vector res depends rather chaotically on the integer argument i. If the last argument is ‘false’ res will have R-typed components, and C-typed components else.
# File linalg.rb, line 71
71: def Vec.tob(n,i,complex=false)
72: vi = complex ? C.tob(i) : R.tob(i)
73: res=Vec.new(n, vi)
74: if complex
75: rg1 = Ran.new(-vi.re,vi.re)
76: rg2 = Ran.new(-vi.im,vi.im)
77: for j in 1..res.dim
78: res[j] = C.new(rg1.ran,rg2.ran)
79: end
80: else
81: rg = Ran.new(-vi,vi)
82: for j in 1..res.dim
83: res[j] = rg.ran
84: end
85: end
86: res
87: end
Returns self * s, where s has the same type as the components of self.
# File linalg.rb, line 160
160: def *(s)
161: res = clone
162: for i in 1..dim
163: res[i] *= s
164: end
165: res
166: end
Returns -self.
# File linalg.rb, line 169
169: def -@
170: res = clone
171: for i in 1..dim
172: res[i] = -res[i]
173: end
174: res
175: end
The order relation is here lexicographic ordering of lists. Needed only for book-keeping purposes. Defines the functionality of self as a Comparable.
# File linalg.rb, line 197
197: def <=> (v)
198: d1 = dim; d2 = v.dim
199: if d1 < d2
200: return -1
201: elsif d1 > d2
202: return 1
203: else
204: for i in 0...d1
205: ci = x[i] <=> v.x[i]
206: return ci unless ci == 0
207: end
208: end
209: return 0
210: end
Valid indexes start with 1 not with 0. Read access to the components also works via indexes such as
y = x[3]
# File linalg.rb, line 126
126: def [](i)
127: @x[i-1]
128: end
Valid indexes start with 1 not with 0. Write access to the components also works via indexes such as
x[1] = 3.14
# File linalg.rb, line 133
133: def []=(i,a)
134: @x[i-1] = a
135: end
Returns the absolute value of self. This is also known as the L2-norm.
# File linalg.rb, line 249
249: def abs
250: if complex?
251: abs2.re.sqrt
252: else
253: abs2.sqrt
254: end
255: end
Returns the square of absolute value of self.
# File linalg.rb, line 243
243: def abs2
244: spr(self)
245: end
Returns an independent copy of self.
# File linalg.rb, line 62
62: def clone
63: Vec.new(self)
64: end
Returns a ‘modified scalar product’ in which no complex conjugation is involved.
# File linalg.rb, line 232
232: def convolution(v)
233: fail "dimension mismatch" unless dim == v.dim
234: return nil if dim.zero?
235: s = self[1] * v[1]
236: for i in 2..dim
237: s += self[i] * v[i]
238: end
239: s
240: end
Returns the ‘dimension’ of the vector, i.e. the number of its components.
# File linalg.rb, line 36
36: def dim; @x.size; end
Returns a relative distance between self and v.
# File linalg.rb, line 270
270: def dis(v)
271: a = abs
272: b = v.abs
273: d = (self - v).abs
274: s = a + b
275: return R.c0 if s.zero?
276: d1 = d/s
277: Basics.inf(d,d1)
278: end
Defines the functionality of self as an Enumerable.
# File linalg.rb, line 213
213: def each
214: @x.each{ |c| yield c}
215: end
Prints the content of self and naming the output.
# File linalg.rb, line 188
188: def prn(name)
189: for i in 1..dim
190: puts " #{name}[#{i}] = " + self[i].to_s
191: end
192: end
Gives the pseudoinverse of the vector self. This means that all components get inverted except those that are close to zero in comparison to the component with the largest absolute value. For small components c ( |c| ~ acc * sup |self[i]| ) a continuous transition between the inverse and zero becomes operational.
# File linalg.rb, line 96
96: def pseudo_inv(acc=0)
97: n = dim
98: fail "dim = 0" if n.zero?
99: res = clone
100: if acc.zero? # most common case, thus first and without ordering
101: # overhead
102: for i in 1..n
103: si = self[i]
104: res[i] = si.zero? ? si.to_0 : si.inv
105: end
106: else
107: arr = @x.clone
108: arr.each{ |v| v = v.abs }
109: arr.sort!
110: a_max = arr.last
111: eta = a_max * acc
112: eta *= 0.5
113: eta *= eta
114: for i in 1..n
115: si = self[i]
116: ni = si * si + eta
117: res[i] = si / ni
118: end
119: end
120: res
121: end
Returns the scalar product (self|v). The complex conjugation (which acts trivially on R) affects here the first factor. This is the convention preferred in physics.
# File linalg.rb, line 220
220: def spr(v)
221: fail "dimension mismatch" unless dim == v.dim
222: return nil if dim.zero?
223: s = self[1].conj * v[1]
224: for i in 2..dim
225: s += self[i].conj * v[i]
226: end
227: s
228: end