kmat
Kmat is a Ruby gem for matrix operations. Kmat uses BLAS/LAPACK as back-end.
Requirements
BLAS/LAPACK libraries are needed to build kmat. MKL can also be used.
You need to modify extconf.rb to use the other BLAS/LAPACK compatible libraries (pull requests are welcome).
Installation
Kmat is available on RubyGems.org:
$ gem install kmat
or in your Gemfile:
gem 'kmat'
Usage
While the gem name is kmat, the top module of this gem is the class Mat
. Most of the functions of kmat are defined under Mat
(some monkey patches (e.g. Random#randn
) are applied to built-in modules/classes).
Mat
is a class of matricies. It has matrix operations as methods. Unlike numpy in Python, Mat
cannot be a tensor with order other than 2. Mat
with shape (n, 1)
or (1, n)
behaves as a vector (not be distinguished from each other) in some methods (e.g. Mat#iprod
).
Matlab style expected return value comments appear in the following sample codes, but they are only in documents (kmat has no way to generate these strings from Mat instances nor way to generate Mat instances from these strings).
Construction of matricies
require 'kmat'
Mat[[1, 2], [3, 4]]
Mat.ones(2, 2)
Mat.eye(2, 2)
Mat.randn(2, 2)
Mat.range(3)
Mat.new(2, 3){|i, j| i+j}
Arithmetic operations
require 'kmat'
a = Mat.ones(2, 2); b = Mat[[2, 0], [0, 1]]
a+b
a-b
a.mprod(b)
a.e_mul(b)
b.under(a)
a.over(b)
a*b
using Mat::MatrixProductOperator
[a*b, a/b]
a.sin
Destructive operation
require 'kmat'
a = Mat.ones(2, 2); b = Mat[[2, 0], [0, 1]]
a+b; a
a.add!(b)
a
c = Mat.new(2, 2)
c.mprod!(a, b)
c
a.sub!(b); a.e_mul!(b); b.e_div!(a); c.under!(b, a)
Numpy-like broadcasting
require 'kmat'
a = Mat.eye(2, 2); b = Mat.range(2)
a+b
a.add!(a.broadcast(b))
a.s_add!(1.5)
0.5 * a
Element or submatrix accessing
rquire 'kmat'
a = Mat[[1, 2], [3, 4]]
a[1, 0]
a[0, -1]
a[nil, 1]
a[[1, 0], 0..1]
a[a.gt(2)]
vidx = Mat.new(1, 2, :object){ |i, j| [j, i] }
a[vidx]
b = a[0, nil]
a[0, 0] = 5
b
b[0, 1] = -1
a
b.freeze
a[0, 0] = -3
b
a.deep_freeze
b[0, 0] = 7
c = a[0, nil]
c[0, 0] = 9
a = Mat[[1, 2], [3, 4]]
a[nil, 0] = Mat.range(2)
a
a.map(&:-@)
a.map_with_index!{|e, i, j| e+j}
a.diag
a[]
Mat.range(3)[2]
Value types
Mat in kmat has 5 value types.
Float
The default value type is :float
. Values are double
in C language and it is compatible with Float
in Ruby. Most of linear argebraic operations are available only on float matricies.
Complex
:complex
is available to deal with complex floats. Some operations are defined but the number of available operations is limitted.
Int
:int
can be used as row or column index array. Values are int
in C language, so it is not useful for matrix operations with large integer elements. We recomend to use :object
with Integer
for such usage.
Bool
:bool
can be used as boolean indexing. Logical operations are available. In some operations, elements in boolean matricies behave as a finite filed with order 2 (+
is exclusive disjunction and *
is logical conjunction).
Object
:object
matricies can contain arbitrary Ruby objects. Operation behaviors are dependent on methods defined for the objects. For example, Mat#solve
works if K#==
, K#quo
, K#*
and K#-
are defined appropriately, where K
is a class of the elements.
:object
matricies with 2-length Array
s are used as indecies for other Mat
s.
rquire 'kmat'
Mat.new(2, 2, :float){|i, j| i+j}
Mat.new(2, 2, :complex){|i, j| Complex.rect(i, j)}
Mat.new(2, 2, :int){|i, j| i-j}
Mat.new(2, 2, :bool){|i, j| i==j}
Mat.new(2, 2, :object){|i, j| Rational(i, j+1) }
Mat.new(1, 1).vtype
Sort, stacking and logical operations
require 'kmat'
a = Mat[[3, 2, 1], [5, -3, 7]]
a.sort(:row)
a.rsort(:col)
a.flip(:both)
a.t
b = Mat.range(2)
Mat.blocks([[a, b], [b, a]])
Mat.vstack(a, a); Mat.hstack(a, b)
a.gt(b)
a.eq(b); a.ge(b); a.lt(b); a.le(b)
a.max
a.maximum(b)
Mat.maximum(a, b.repmat(1, 3), Mat.randn(2, 3))
Linear algebraic operations
Most of them are useing BLAS/LAPACK as a back-end.
require 'kmat'
a, b = Mat.randn(3, 3), Mat.rand(3, 1)
a.ls(b)
a.evd
a.svd
a.lup
a.det
a.qr
Mat.rand_orth(3)
a.tr
Copying elements
require 'kmat'
a, b = Mat.randn(2, 2), Mat.randn(2, 2)
a.dup
a.copy_from(b)
a.replace(b[])
a.fill(1.5)
Marshal.load(Marshal.dump(a))
Random
require 'kmat'
Mat.randn(2, 2, random: Random.new)
$MatRandom = Random.new
Random.new.randn
randn()
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/cycloawaodorin/kmat.
License
Kmat is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version3 of the License, or (at your option) any later version.
Kmat is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with the gem; see the file LICENSE.md. If not, see the website of GPL.
The header files under /ext/lapack_headers/
directory are modified or copied version of an Azalea Clive's product or Intel Corp's products. The original versions are distributed at the following.
blas.h
is distributed at BLASの簡単な使い方.
lapacke.h
, lapacke_config.h
, lapacke_mangling.h
and lapacke_utils.h
are distributed at the website of LAPACKE under modified BSD license.