NMatrix, NVector


NMatrix

A subclass of NArray. First two dimensions are used for Matrix. Following dimensions are regarded as multi-dimensional array in the same way as NArray.

Subscript order is reversed in NMatrix from the conventional mathematical notation (aij = a[j,i]) , because NArray's dimension order follows FORTRAN style.

NVector

A subclass of NArray. First one dimension is used for Vector. Following dimensions are regarded as multi-dimensional array.

Operation

In contrast to Element-wise operation of NArray, NMatrix and NVector provide Matrix/Vector-wise operations.

In the operations between NMatrix/NVector and NArray, NArray works as Scalar. The dimensions following the class dimension(s) work in the same way as NArray's dimension.

This makes it easy to handle, e.g., a 100x100 two-dimensional array of 3-dimensional Vector. (Quiz: How many dimensional array is this?)

Example:
  
% irb -r nmatrix

irb(main):001:0> m = NMatrix.float(2,2).indgen!
NMatrix.float(2,2): 
[ [ 0.0, 1.0 ], 
  [ 2.0, 3.0 ] ]

irb(main):002:0> a = NArray.float(2).indgen!+1
NArray.float(2): 
[ 1.0, 2.0 ]

irb(main):003:0> a * m
NMatrix.float(2,2,2): 
[ [ [ 0.0, 1.0 ], 
    [ 2.0, 3.0 ] ], 
  [ [ 0.0, 2.0 ], 
    [ 4.0, 6.0 ] ] ]

irb(main):004:0> a + m
TypeError: Illegal operation: NArray + NMatrix
./nmatrix.rb:109:in `coerce_rev'
(irb):4:in `+'
(irb):4:in `irb_binding'


Slicing

Slicing rules for NMatrix/NVector are slightly different from NArray's: Example:
  
% irb -r nmatrix

irb(main):001:0> m = NMatrix.float(2,2,2).indgen!
NMatrix.float(2,2,2): 
[ [ [ 0.0, 1.0 ], 
    [ 2.0, 3.0 ] ], 
  [ [ 4.0, 5.0 ], 
    [ 6.0, 7.0 ] ] ]

irb(main):002:0> m[1,1,true]
NArray.float(2): 
[ 3.0, 7.0 ]

irb(main):003:0> m[0..1,1,true] 
NMatrix.float(2,1,2): 
[ [ [ 2.0, 3.0 ] ], 
  [ [ 6.0, 7.0 ] ] ]

Solve Linear Equation

When m is square NMatrix, x and y are NVector and m and y are given, to solve the linear equation
  
  y = m * x
to obtain x, you simply write
  
  x = y / m
This is equivalent to
  
  x = m.lu.solve(y)
So this include two steps: You can save the result of NMatrix#lu to a variable, and recycle it

You should pay attention to the order of notation:
  
  x = y / m
is mathmatically equivalent to
  
  x = m**-1 * y

You can LU factorize Ruby Object arrays;
  
% irb -r nmatrix -r rational

irb(main):001:0> m = NMatrix.object(4,4).collect!{Rational(rand(10))}
NMatrix.object(4,4): 
[ [ Rational(3, 1), Rational(6, 1), Rational(5, 1), Rational(3, 1) ], 
  [ Rational(1, 1), Rational(6, 1), Rational(2, 1), Rational(0, 1) ], 
  [ Rational(0, 1), Rational(3, 1), Rational(1, 1), Rational(7, 1) ], 
  [ Rational(2, 1), Rational(8, 1), Rational(9, 1), Rational(1, 1) ] ]

irb(main):002:0> m/m
NMatrix.object(4,4): 
[ [ Rational(1, 1), Rational(0, 1), Rational(0, 1), Rational(0, 1) ], 
  [ Rational(0, 1), Rational(1, 1), Rational(0, 1), Rational(0, 1) ], 
  [ Rational(0, 1), Rational(0, 1), Rational(1, 1), Rational(0, 1) ], 
  [ Rational(0, 1), Rational(0, 1), Rational(0, 1), Rational(1, 1) ] ]


Back to Numerical Ruby
Masahiro Tanaka <masa at ir.isas.ac.jp>
Last modified: Nov 22, 2000