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