# Class: Vector

Inherits:
Object
• Object
show all
Extended by:
Matrix::ConversionHelper
Includes:
Enumerable, ExceptionForMatrix, Matrix::CoercionHelper
Defined in:
lib/matrix.rb

## Overview

The `Vector` class represents a mathematical vector, which is useful in its own right, and also constitutes a row or column of a Matrix.

## Method Catalogue

To create a Vector:

• Vector.[](*array)

• Vector.elements(array, copy = true)

• Vector.basis(size: n, index: k)

• Vector.zero(n)

To access elements:

• #[](i)

To set elements:

• #[]=(i, v)

To enumerate the elements:

• #each2(v)

• #collect2(v)

Properties of vectors:

• #angle_with(v)

• Vector.independent?(*vs)

• #independent?(*vs)

• #zero?

Vector arithmetic:

• #*(x) “is matrix or number”

• #+(v)

• #-(v)

• #/(v)

• #+@

• #-@

Vector functions:

• #inner_product(v), #dot(v)

• #cross_product(v), #cross(v)

• #collect

• #collect!

• #magnitude

• #map

• #map!

• #map2(v)

• #norm

• #normalize

• #r

• #round

• #size

Conversion to other data types:

• #covector

• #to_a

• #coerce(other)

String representations:

• #to_s

• #inspect

## Defined Under Namespace

Classes: ZeroVectorError

## Class Method Summary collapse

• Creates a Vector from a list of elements.

• Returns a standard basis `n`-vector, where k is the index.

• Creates a vector from an Array.

• Returns `true` iff all of vectors are linearly independent.

• Return a zero vector.

## Instance Method Summary collapse

• Multiplies the vector by `x`, where `x` is a number or a matrix.

• Vector subtraction.

• Vector division.

• Returns `true` iff the two vectors have the same elements in the same order.

• #[](i) ⇒ Object (also: #element, #component)

:call-seq: vector vector.

• #[]=(i, v) ⇒ Object (also: #set_element, #set_component)

:call-seq: vector = new_vector vector = row_matrix vector = new_element vector = new_element.

• Returns an angle with another vector.

• The coerce method provides support for Ruby type coercion.

• #collect(&block) ⇒ Object (also: #map)

Like Array#collect.

• #collect!(&block) ⇒ Object (also: #map!)

Like Array#collect!.

• Collects (as in Enumerable#collect) over the elements of this vector and `v` in conjunction.

• Creates a single-row matrix from this vector.

• #cross_product(*vs) ⇒ Object (also: #cross)

Returns the cross product of this vector with the others.

• Iterate over the elements of this vector.

• Iterate over the elements of this vector and `v` in conjunction.

• Makes the matrix frozen and Ractor-shareable.

• Returns a hash-code for the vector.

• Returns `true` iff all of vectors are linearly independent.

• constructor

Vector.new is private; use Vector[] or Vector.elements to create.

• #inner_product(v) ⇒ Object (also: #dot)

Returns the inner product of this vector with the other.

• Overrides Object#inspect.

• #magnitude ⇒ Object (also: #r, #norm)

Returns the modulus (Pythagorean distance) of the vector.

• Like Vector#collect2, but returns a Vector instead of an Array.

• Returns a new vector with the same direction but with norm 1.

• Returns a vector with entries rounded to the given precision (see Float#round).

• Returns the number of elements in the vector.

• Returns the elements of the vector in an array.

• Return a single-column matrix from this vector.

• Overrides Object#to_s.

• Returns `true` iff all elements are zero.

## Constructor Details

### #initialize(array) ⇒ Vector

Vector.new is private; use Vector[] or Vector.elements to create.

 ``` 1991 1992 1993 1994``` ```# File 'lib/matrix.rb', line 1991 def initialize(array) # No checking is done at this point. @elements = array end ```

## Class Method Details

### .[](*array) ⇒ Object

Creates a Vector from a list of elements.

``````Vector[7, 4, ...]
``````
 ``` 1952 1953 1954``` ```# File 'lib/matrix.rb', line 1952 def Vector.[](*array) new convert_to_array(array, false) end ```

### .basis(size:, index:) ⇒ Object

Returns a standard basis `n`-vector, where k is the index.

``````Vector.basis(size:, index:) # => Vector[0, 1, 0]
``````

Raises:

• (ArgumentError)
 ``` 1969 1970 1971 1972 1973 1974 1975``` ```# File 'lib/matrix.rb', line 1969 def Vector.basis(size:, index:) raise ArgumentError, "invalid size (#{size} for 1..)" if size < 1 raise ArgumentError, "invalid index (#{index} for 0...#{size})" unless 0 <= index && index < size array = Array.new(size, 0) array[index] = 1 new convert_to_array(array, false) end ```

### .elements(array, copy = true) ⇒ Object

Creates a vector from an Array. The optional second argument specifies whether the array itself or a copy is used internally.

 ``` 1960 1961 1962``` ```# File 'lib/matrix.rb', line 1960 def Vector.elements(array, copy = true) new convert_to_array(array, copy) end ```

### .independent?(*vs) ⇒ Boolean

Returns `true` iff all of vectors are linearly independent.

``````Vector.independent?(Vector[1,0], Vector[0,1])
#  => true

Vector.independent?(Vector[1,2], Vector[2,4])
#  => false
``````

Returns:

• (Boolean)
 ``` 2116 2117 2118 2119 2120 2121 2122 2123``` ```# File 'lib/matrix.rb', line 2116 def Vector.independent?(*vs) vs.each do |v| raise TypeError, "expected Vector, got #{v.class}" unless v.is_a?(Vector) raise ErrDimensionMismatch unless v.size == vs.first.size end return false if vs.count > vs.first.size Matrix[*vs].rank.eql?(vs.count) end ```

### .zero(size) ⇒ Object

Return a zero vector.

``````Vector.zero(3) # => Vector[0, 0, 0]
``````

Raises:

• (ArgumentError)
 ``` 1982 1983 1984 1985 1986``` ```# File 'lib/matrix.rb', line 1982 def Vector.zero(size) raise ArgumentError, "invalid size (#{size} for 0..)" if size < 0 array = Array.new(size, 0) new convert_to_array(array, false) end ```

## Instance Method Details

### #*(x) ⇒ Object

Multiplies the vector by `x`, where `x` is a number or a matrix.

 ``` 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205``` ```# File 'lib/matrix.rb', line 2193 def *(x) case x when Numeric els = @elements.collect{|e| e * x} self.class.elements(els, false) when Matrix Matrix.column_vector(self) * x when Vector raise ErrOperationNotDefined, ["*", self.class, x.class] else apply_through_coercion(x, __method__) end end ```

### #+(v) ⇒ Object

 ``` 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223``` ```# File 'lib/matrix.rb', line 2210 def +(v) case v when Vector raise ErrDimensionMismatch if size != v.size els = collect2(v) {|v1, v2| v1 + v2 } self.class.elements(els, false) when Matrix Matrix.column_vector(self) + v else apply_through_coercion(v, __method__) end end ```

### #+@ ⇒ Object

 ``` 2258 2259 2260``` ```# File 'lib/matrix.rb', line 2258 def +@ self end ```

### #-(v) ⇒ Object

Vector subtraction.

 ``` 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241``` ```# File 'lib/matrix.rb', line 2228 def -(v) case v when Vector raise ErrDimensionMismatch if size != v.size els = collect2(v) {|v1, v2| v1 - v2 } self.class.elements(els, false) when Matrix Matrix.column_vector(self) - v else apply_through_coercion(v, __method__) end end ```

### #-@ ⇒ Object

 ``` 2262 2263 2264``` ```# File 'lib/matrix.rb', line 2262 def -@ collect {|e| -e } end ```

### #/(x) ⇒ Object

Vector division.

 ``` 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256``` ```# File 'lib/matrix.rb', line 2246 def /(x) case x when Numeric els = @elements.collect{|e| e / x} self.class.elements(els, false) when Matrix, Vector raise ErrOperationNotDefined, ["/", self.class, x.class] else apply_through_coercion(x, __method__) end end ```

### #==(other) ⇒ Object

Returns `true` iff the two vectors have the same elements in the same order.

 ``` 2169 2170 2171 2172``` ```# File 'lib/matrix.rb', line 2169 def ==(other) return false unless Vector === other @elements == other.elements end ```

### #[](i) ⇒ ObjectAlso known as: element, component

:call-seq:

``````vector[range]
vector[integer]
``````

Returns element or elements of the vector.

 ``` 2005 2006 2007``` ```# File 'lib/matrix.rb', line 2005 def [](i) @elements[i] end ```

### #[]=(i, v) ⇒ ObjectAlso known as: set_element, set_component

:call-seq:

``````vector[range] = new_vector
vector[range] = row_matrix
vector[range] = new_element
vector[integer] = new_element
``````

Set element or elements of vector.

Raises:

• (FrozenError)
 ``` 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029``` ```# File 'lib/matrix.rb', line 2020 def []=(i, v) raise FrozenError, "can't modify frozen Vector" if frozen? if i.is_a?(Range) range = Matrix::CoercionHelper.check_range(i, size, :vector) set_range(range, v) else index = Matrix::CoercionHelper.check_int(i, size, :index) set_value(index, v) end end ```

### #angle_with(v) ⇒ Object

Returns an angle with another vector. Result is within the [0..Math::PI].

``````Vector[1,0].angle_with(Vector[0,1])
# => Math::PI / 2
``````

Raises:

• (TypeError)
 ``` 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389``` ```# File 'lib/matrix.rb', line 2378 def angle_with(v) raise TypeError, "Expected a Vector, got a #{v.class}" unless v.is_a?(Vector) raise ErrDimensionMismatch if size != v.size prod = magnitude * v.magnitude raise ZeroVectorError, "Can't get angle of zero vector" if prod == 0 dot = inner_product(v) if dot.abs >= prod dot.positive? ? 0 : Math::PI else Math.acos(dot / prod) end end ```

### #coerce(other) ⇒ Object

The coerce method provides support for Ruby type coercion. This coercion mechanism is used by Ruby to handle mixed-type numeric operations: it is intended to find a compatible common type between the two operands of the operator. See also Numeric#coerce.

 ``` 2438 2439 2440 2441 2442 2443 2444 2445``` ```# File 'lib/matrix.rb', line 2438 def coerce(other) case other when Numeric return Matrix::Scalar.new(other), self else raise TypeError, "#{self.class} can't be coerced into #{other.class}" end end ```

### #collect(&block) ⇒ ObjectAlso known as: map

Like Array#collect.

 ``` 2322 2323 2324 2325 2326``` ```# File 'lib/matrix.rb', line 2322 def collect(&block) # :yield: e return to_enum(:collect) unless block_given? els = @elements.collect(&block) self.class.elements(els, false) end ```

### #collect!(&block) ⇒ ObjectAlso known as: map!

Like Array#collect!

Raises:

• (FrozenError)
 ``` 2332 2333 2334 2335 2336 2337``` ```# File 'lib/matrix.rb', line 2332 def collect!(&block) return to_enum(:collect!) unless block_given? raise FrozenError, "can't modify frozen Vector" if frozen? @elements.collect!(&block) self end ```

### #collect2(v) ⇒ Object

Collects (as in Enumerable#collect) over the elements of this vector and `v` in conjunction.

Raises:

• (TypeError)
 ``` 2094 2095 2096 2097 2098 2099 2100 2101``` ```# File 'lib/matrix.rb', line 2094 def collect2(v) # :yield: e1, e2 raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) raise ErrDimensionMismatch if size != v.size return to_enum(:collect2, v) unless block_given? Array.new(size) do |i| yield @elements[i], v[i] end end ```

### #covector ⇒ Object

Creates a single-row matrix from this vector.

 ``` 2398 2399 2400``` ```# File 'lib/matrix.rb', line 2398 def covector Matrix.row_vector(self) end ```

### #cross_product(*vs) ⇒ ObjectAlso known as: cross

Returns the cross product of this vector with the others.

``````Vector[1, 0, 0].cross_product Vector[0, 1, 0]  # => Vector[0, 0, 1]
``````

It is generalized to other dimensions to return a vector perpendicular to the arguments.

``````Vector[1, 2].cross_product # => Vector[-2, 1]
Vector[1, 0, 0, 0].cross_product(
Vector[0, 1, 0, 0],
Vector[0, 0, 1, 0]
)  #=> Vector[0, 0, 0, 1]
``````

Raises:

 ``` 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316``` ```# File 'lib/matrix.rb', line 2297 def cross_product(*vs) raise ErrOperationNotDefined, "cross product is not defined on vectors of dimension #{size}" unless size >= 2 raise ArgumentError, "wrong number of arguments (#{vs.size} for #{size - 2})" unless vs.size == size - 2 vs.each do |v| raise TypeError, "expected Vector, got #{v.class}" unless v.is_a? Vector raise ErrDimensionMismatch unless v.size == size end case size when 2 Vector[-@elements[1], @elements[0]] when 3 v = vs[0] Vector[ v[2]*@elements[1] - v[1]*@elements[2], v[0]*@elements[2] - v[2]*@elements[0], v[1]*@elements[0] - v[0]*@elements[1] ] else rows = self, *vs, Array.new(size) {|i| Vector.basis(size: size, index: i) } Matrix.rows(rows).laplace_expansion(row: size - 1) end end ```

### #each(&block) ⇒ Object

Iterate over the elements of this vector

 ``` 2071 2072 2073 2074 2075``` ```# File 'lib/matrix.rb', line 2071 def each(&block) return to_enum(:each) unless block_given? @elements.each(&block) self end ```

### #each2(v) ⇒ Object

Iterate over the elements of this vector and `v` in conjunction.

Raises:

• (TypeError)
 ``` 2080 2081 2082 2083 2084 2085 2086 2087 2088``` ```# File 'lib/matrix.rb', line 2080 def each2(v) # :yield: e1, e2 raise TypeError, "Integer is not like Vector" if v.kind_of?(Integer) raise ErrDimensionMismatch if size != v.size return to_enum(:each2, v) unless block_given? size.times do |i| yield @elements[i], v[i] end self end ```

### #elements_to_f ⇒ Object

 ``` 2416 2417 2418 2419``` ```# File 'lib/matrix.rb', line 2416 def elements_to_f warn "Vector#elements_to_f is deprecated", uplevel: 1 map(&:to_f) end ```

### #elements_to_i ⇒ Object

 ``` 2421 2422 2423 2424``` ```# File 'lib/matrix.rb', line 2421 def elements_to_i warn "Vector#elements_to_i is deprecated", uplevel: 1 map(&:to_i) end ```

### #elements_to_r ⇒ Object

 ``` 2426 2427 2428 2429``` ```# File 'lib/matrix.rb', line 2426 def elements_to_r warn "Vector#elements_to_r is deprecated", uplevel: 1 map(&:to_r) end ```

### #eql?(other) ⇒ Boolean

Returns:

• (Boolean)
 ``` 2174 2175 2176 2177``` ```# File 'lib/matrix.rb', line 2174 def eql?(other) return false unless Vector === other @elements.eql? other.elements end ```

### #freeze ⇒ Object

Makes the matrix frozen and Ractor-shareable

 ``` 2148 2149 2150 2151``` ```# File 'lib/matrix.rb', line 2148 def freeze @elements.freeze super end ```

### #hash ⇒ Object

Returns a hash-code for the vector.

 ``` 2182 2183 2184``` ```# File 'lib/matrix.rb', line 2182 def hash @elements.hash end ```

### #independent?(*vs) ⇒ Boolean

Returns `true` iff all of vectors are linearly independent.

``````Vector[1,0].independent?(Vector[0,1])
# => true

Vector[1,2].independent?(Vector[2,4])
# => false
``````

Returns:

• (Boolean)
 ``` 2134 2135 2136``` ```# File 'lib/matrix.rb', line 2134 def independent?(*vs) self.class.independent?(self, *vs) end ```

### #inner_product(v) ⇒ ObjectAlso known as: dot

Returns the inner product of this vector with the other.

``````Vector[4,7].inner_product Vector[10,1] # => 47
``````

Raises:

 ``` 2274 2275 2276 2277 2278 2279 2280 2281 2282``` ```# File 'lib/matrix.rb', line 2274 def inner_product(v) raise ErrDimensionMismatch if size != v.size p = 0 each2(v) {|v1, v2| p += v1 * v2.conj } p end ```

### #inspect ⇒ Object

Overrides Object#inspect

 ``` 2461 2462 2463``` ```# File 'lib/matrix.rb', line 2461 def inspect "Vector" + @elements.inspect end ```

### #magnitude ⇒ ObjectAlso known as: r, norm

Returns the modulus (Pythagorean distance) of the vector.

``````Vector[5,8,2].r # => 9.643650761
``````
 ``` 2344 2345 2346``` ```# File 'lib/matrix.rb', line 2344 def magnitude Math.sqrt(@elements.inject(0) {|v, e| v + e.abs2}) end ```

### #map2(v, &block) ⇒ Object

Like Vector#collect2, but returns a Vector instead of an Array.

 ``` 2353 2354 2355 2356 2357``` ```# File 'lib/matrix.rb', line 2353 def map2(v, &block) # :yield: e1, e2 return to_enum(:map2, v) unless block_given? els = collect2(v, &block) self.class.elements(els, false) end ```

### #normalize ⇒ Object

Returns a new vector with the same direction but with norm 1.

``````v = Vector[5,8,2].normalize
# => Vector[0.5184758473652127, 0.8295613557843402, 0.20739033894608505]
v.norm # => 1.0
``````

Raises:

 ``` 2367 2368 2369 2370 2371``` ```# File 'lib/matrix.rb', line 2367 def normalize n = magnitude raise ZeroVectorError, "Zero vectors can not be normalized" if n == 0 self / n end ```

### #round(ndigits = 0) ⇒ Object

Returns a vector with entries rounded to the given precision (see Float#round)

 ``` 2053 2054 2055``` ```# File 'lib/matrix.rb', line 2053 def round(ndigits=0) map{|e| e.round(ndigits)} end ```

### #size ⇒ Object

Returns the number of elements in the vector.

 ``` 2060 2061 2062``` ```# File 'lib/matrix.rb', line 2060 def size @elements.size end ```

### #to_a ⇒ Object

Returns the elements of the vector in an array.

 ``` 2405 2406 2407``` ```# File 'lib/matrix.rb', line 2405 def to_a @elements.dup end ```

### #to_matrix ⇒ Object

Return a single-column matrix from this vector

 ``` 2412 2413 2414``` ```# File 'lib/matrix.rb', line 2412 def to_matrix Matrix.column_vector(self) end ```

### #to_s ⇒ Object

Overrides Object#to_s

 ``` 2454 2455 2456``` ```# File 'lib/matrix.rb', line 2454 def to_s "Vector[" + @elements.join(", ") + "]" end ```

### #zero? ⇒ Boolean

Returns `true` iff all elements are zero.

Returns:

• (Boolean)
 ``` 2141 2142 2143``` ```# File 'lib/matrix.rb', line 2141 def zero? all?(&:zero?) end ```