Class: AppMath::Vec
- Inherits:
-
Object
- Object
- AppMath::Vec
- Includes:
- Comparable, Enumerable
- Defined in:
- lib/linalg.rb
Overview
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.
Instance Attribute Summary collapse
-
#x ⇒ Object
Returns the value of attribute x.
Class Method Summary collapse
-
.test(n0, verbose = true, complex = false) ⇒ Object
Consistency test of class Vec.
-
.tob(n, i, complex = false) ⇒ Object
Test object.
Instance Method Summary collapse
-
#*(s) ⇒ Object
Returns self * s, where s has the same type as the components of self.
-
#+(v) ⇒ Object
Returns self + v, where v is a Vec.
-
#-(v) ⇒ Object
Returns self - v , where v is a Vec.
-
#-@ ⇒ Object
Returns -self.
-
#<=>(v) ⇒ Object
The order relation is here lexicographic ordering of lists.
-
#[](i) ⇒ Object
Valid indexes start with 1 not with 0.
-
#[]=(i, a) ⇒ Object
Valid indexes start with 1 not with 0.
-
#abs ⇒ Object
Returns the absolute value of self.
-
#abs2 ⇒ Object
Returns the square of absolute value of self.
-
#clone ⇒ Object
Returns an independent copy of self.
-
#complex? ⇒ Boolean
Returns ‘true’ if the first component is complex.
-
#convolution(v) ⇒ Object
Returns a ‘modified scalar product’ in which no complex conjugation is involved.
-
#dim ⇒ Object
Returns the ‘dimension’ of the vector, i.e.
-
#dis(v) ⇒ Object
Returns a relative distance between self and v.
-
#each ⇒ Object
Defines the functionality of self as an Enumerable.
-
#initialize(*arg) ⇒ Vec
constructor
These are the 3 mehods to generate a vector via ‘new’ a = Vec.new(anArray) b = Vec.new(aVec) c = Vec.new(aPositiveInteger, aRealOrComplex).
-
#prn(name) ⇒ Object
Prints the content of self and naming the output.
-
#pseudo_inv(acc = 0) ⇒ Object
Gives the pseudoinverse of the vector self.
-
#spr(v) ⇒ Object
Returns the scalar product (self|v).
-
#to_s ⇒ Object
Returns a string which consists of a list of the strings which represent the components.
-
#uv ⇒ Object
Returns a unit vector which has the same direction as self, (or self if this is the zero-vector).
Constructor Details
#initialize(*arg) ⇒ Vec
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/linalg.rb', line 59 def initialize(*arg) case arg.size when 1 a0 = arg[0] if a0.is_a?(Array) @x = Array.new(a0) # @x = a0 # seems to work but can't be safe elsif a0.is_a?(Vec) @x = Array.new(a0.x) else fail "object can't be used to build a vector" end when 2 n = arg[0] fail "first argument has to be an integer" unless n.integer? fail "first argument must be non-negative" unless n >= 0 @x = Array.new(n,arg[1]) end end |
Instance Attribute Details
#x ⇒ Object
Returns the value of attribute x.
49 50 51 |
# File 'lib/linalg.rb', line 49 def x @x end |
Class Method Details
.test(n0, verbose = true, complex = false) ⇒ Object
Consistency test of class Vec.
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
# File 'lib/linalg.rb', line 307 def Vec.test(n0, verbose = true , complex = false) puts "Doing Vec.test( n = #{n0}, verbose = #{verbose}, " + "complex = #{complex}) for R.prec = #{R.prec}:" puts "*************************************************" t1 = Time.now s = R.c0 puts "class of s is " + s.class.to_s i = n0 a = Vec.tob(n0, i, complex) i += 1 b = Vec.tob(n0, i, complex) i += 1 c = Vec.tob(n0, i, complex) i += 1 s1 = complex ? C.ran(i) : R.ran(i) i += 1 s2 = complex ? C.ran(i) : R.ran(i) r = (a + b) + c l = a + (b + c) ds = r.dis(l) puts "associativity: ds = " + ds.to_s if verbose s += ds r = (a - b) + c l = a - (b - c) ds = r.dis(l) puts "associativity 2: ds = " + ds.to_s if verbose s += ds r = (a + b) * s1 l = a * s1 + b * s1 ds = r.dis(l) puts "distributivity: ds = " + ds.to_s if verbose s += ds r = c * (s1*s2) l = (c * s1) * s2 ds = r.dis(l) puts "distributivity of multiplication by scalars: ds = " + ds.to_s if verbose s += ds r = a l = -(-a) ds = r.dis(l) puts "idempotency of unary minus: ds = " + ds.to_s if verbose s += ds r = (a + b).spr(c) l = a.spr(c) + b.spr(c) ds = r.dis(l) puts "distributivity of spr: ds = " + ds.to_s if verbose s += ds t2 = Time.now if verbose puts a.prn("a") puts b.prn("b") puts c.prn("c") puts s1.prn("s1") puts s2.prn("s2") end puts "class of s is " + s.class.to_s + " ." puts "The error sum s is " + s.to_s + " ." puts "It should be close to 0." puts "Computation time was " + (t2-t1).to_s s end |
.tob(n, i, complex = false) ⇒ Object
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.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/linalg.rb', line 89 def Vec.tob(n,i,complex=false) vi = complex ? C.tob(i) : R.tob(i) res=Vec.new(n, vi) if complex rg1 = Ran.new(-vi.re,vi.re) rg2 = Ran.new(-vi.im,vi.im) for j in 1..res.dim res[j] = C.new(rg1.ran,rg2.ran) end else rg = Ran.new(-vi,vi) for j in 1..res.dim res[j] = rg.ran end end res end |
Instance Method Details
#*(s) ⇒ Object
Returns self * s, where s has the same type as the components of self.
178 179 180 181 182 183 184 |
# File 'lib/linalg.rb', line 178 def *(s) res = clone for i in 1..dim res[i] *= s end res end |
#+(v) ⇒ Object
Returns self + v, where v is a Vec
156 157 158 159 160 161 162 163 164 |
# File 'lib/linalg.rb', line 156 def +(v) fail "object can't be added to a Vec" unless v.is_a?(Vec) fail "dimension mismatch" unless dim == v.dim res = clone for i in 1..dim res[i] += v[i] end res end |
#-(v) ⇒ Object
Returns self - v , where v is a Vec
167 168 169 170 171 172 173 174 175 |
# File 'lib/linalg.rb', line 167 def -(v) fail "object can't be subtracted from a Vec" unless v.is_a?(Vec) fail "dimension mismatch" unless dim == v.dim res = clone for i in 1..dim res[i] -= v[i] end res end |
#-@ ⇒ Object
Returns -self.
187 188 189 190 191 192 193 |
# File 'lib/linalg.rb', line 187 def -@ res = clone for i in 1..dim res[i] = -res[i] end res end |
#<=>(v) ⇒ Object
The order relation is here lexicographic ordering of lists. Needed only for book-keeping purposes. Defines the functionality of self as a Comparable.
215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/linalg.rb', line 215 def <=> (v) d1 = dim; d2 = v.dim if d1 < d2 return -1 elsif d1 > d2 return 1 else for i in 0...d1 ci = x[i] <=> v.x[i] return ci unless ci == 0 end end return 0 end |
#[](i) ⇒ Object
Valid indexes start with 1 not with 0. Read access to the components also works via indexes such as
y = x[3]
144 145 146 |
# File 'lib/linalg.rb', line 144 def [](i) @x[i-1] end |
#[]=(i, a) ⇒ Object
Valid indexes start with 1 not with 0. Write access to the components also works via indexes such as
x[1] = 3.14
151 152 153 |
# File 'lib/linalg.rb', line 151 def []=(i,a) @x[i-1] = a end |
#abs ⇒ Object
Returns the absolute value of self. This is also known as the L2-norm.
267 268 269 270 271 272 273 |
# File 'lib/linalg.rb', line 267 def abs if complex? abs2.re.sqrt else abs2.sqrt end end |
#abs2 ⇒ Object
Returns the square of absolute value of self.
261 262 263 |
# File 'lib/linalg.rb', line 261 def abs2 spr(self) end |
#clone ⇒ Object
Returns an independent copy of self.
80 81 82 |
# File 'lib/linalg.rb', line 80 def clone Vec.new(self) end |
#complex? ⇒ Boolean
Returns ‘true’ if the first component is complex. Notice that the normal usage of Vec is to have all components of the same type.
301 302 303 304 |
# File 'lib/linalg.rb', line 301 def complex? return nil if dim.zero? @x[0].complex? end |
#convolution(v) ⇒ Object
Returns a ‘modified scalar product’ in which no complex conjugation is involved.
250 251 252 253 254 255 256 257 258 |
# File 'lib/linalg.rb', line 250 def convolution(v) fail "dimension mismatch" unless dim == v.dim return nil if dim.zero? s = self[1] * v[1] for i in 2..dim s += self[i] * v[i] end s end |
#dim ⇒ Object
Returns the ‘dimension’ of the vector, i.e. the number of its components.
53 |
# File 'lib/linalg.rb', line 53 def dim; @x.size; end |
#dis(v) ⇒ Object
Returns a relative distance between self and v.
288 289 290 291 292 293 294 295 296 |
# File 'lib/linalg.rb', line 288 def dis(v) a = abs b = v.abs d = (self - v).abs s = a + b return R.c0 if s.zero? d1 = d/s Basics.inf(d,d1) end |
#each ⇒ Object
Defines the functionality of self as an Enumerable.
231 232 233 |
# File 'lib/linalg.rb', line 231 def each @x.each{ |c| yield c} end |
#prn(name) ⇒ Object
Prints the content of self and naming the output.
206 207 208 209 210 |
# File 'lib/linalg.rb', line 206 def prn(name) for i in 1..dim puts " #{name}[#{i}] = " + self[i].to_s end end |
#pseudo_inv(acc = 0) ⇒ Object
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| ) a continuous transition between the inverse and zero becomes operational.
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/linalg.rb', line 114 def pseudo_inv(acc=0) n = dim fail "dim = 0" if n.zero? res = clone if acc.zero? # most common case, thus first and without ordering # overhead for i in 1..n si = self[i] res[i] = si.zero? ? si.to_0 : si.inv end else arr = @x.clone arr.each{ |v| v = v.abs } arr.sort! a_max = arr.last eta = a_max * acc eta *= 0.5 eta *= eta for i in 1..n si = self[i] ni = si * si + eta res[i] = si / ni end end res end |
#spr(v) ⇒ Object
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.
238 239 240 241 242 243 244 245 246 |
# File 'lib/linalg.rb', line 238 def spr(v) fail "dimension mismatch" unless dim == v.dim return nil if dim.zero? s = self[1].conj * v[1] for i in 2..dim s += self[i].conj * v[i] end s end |
#to_s ⇒ Object
Returns a string which consists of a list of the strings which represent the components.
197 198 199 200 201 202 203 |
# File 'lib/linalg.rb', line 197 def to_s res = "\n Vec" for i in 0...dim res += "\n " + x[i].to_s end res + "\n end Vec" end |
#uv ⇒ Object
Returns a unit vector which has the same direction as self, (or self if this is the zero-vector).
277 278 279 280 281 282 283 284 285 |
# File 'lib/linalg.rb', line 277 def uv r = abs if r.zero? clone else ri = r.inv self * ri end end |