class RMatrix::M

Constants

OPERATIONS_MAP

Attributes

named_inspect[RW]
column_label_map[RW]
column_map[R]
invert_next_operation[RW]
matrix[W]
narray[RW]
row_label_map[RW]
row_map[R]
typecode[RW]

Public Class Methods

[](*inputs, typecode: Typecode::FLOAT, row_map: nil, column_map: nil, column_label_map: nil, row_label_map: nil) click to toggle source
# File lib/rmatrix/matrix.rb, line 408
def self.[](*inputs, typecode: Typecode::FLOAT, row_map: nil, column_map: nil, column_label_map: nil, row_label_map: nil)
  if inputs.length == 1 && Matrix === inputs[0]
    inputs[0]
  elsif inputs.length == 1 && [String, Symbol].include?(inputs[0].class)
    if ['byte', 'sint', 'int', 'sfloat', 'float', 'scomplex', 'complex', 'object'].include?(inputs[0])
      ->(*source){ Matrix.new(source, inputs[0], row_map: row_map, column_map: column_map, row_label_map: row_label_map, column_label_map: column_label_map)}
    else
      Matrix.new(inputs[0], typecode, row_map: row_map, column_map: column_map, row_label_map: row_label_map, column_label_map: column_label_map)
    end
  else
    Matrix.new(inputs, typecode, row_map: row_map, column_map: column_map, row_label_map: row_label_map, column_label_map: column_label_map)
  end
end
_load(arg) click to toggle source
# File lib/rmatrix/matrix.rb, line 88
def self._load arg
  split_index, buffer, index = 0, '', arg.length - 1
  split = Array.new(3)
  while split_index < 3
    case char = arg[index]
    when ':'
      split[split_index] = buffer.reverse.to_i
      split_index += 1
      buffer = ''
    else buffer << char
    end
    index -= 1
  end
  arg[index+1..-1] = ''
  self.new(NArray.to_na(arg, split[0]).reshape(split[2], split[1]), split[0])
end
blank(rows: 1, columns: 1, typecode: Typecode::FLOAT, initial: 0, column_map: nil, row_map: nil) click to toggle source
# File lib/rmatrix/matrix.rb, line 48
def self.blank(rows: 1, columns: 1, typecode: Typecode::FLOAT, initial: 0, column_map: nil, row_map: nil)
  source = self.new(NArray.new(typecode, columns, rows), typecode, column_map: column_map, row_map: row_map)
  source.narray[]= initial unless source.empty?
  source
end
gen_delegator(name) click to toggle source
# File lib/rmatrix/matrix.rb, line 461
def self.gen_delegator(name)
  define_method(name) do |*args, &blk|
    result = matrix.send(name, *args, &blk)
    case result
    when NArray then Matrix.new(result, typecode)
    else result
    end
  end
end
gen_matrix_delegator(name) click to toggle source
# File lib/rmatrix/matrix.rb, line 442
def self.gen_matrix_delegator(name)
  define_method(name) do |*args, &blk|
    Matrix.new(matrix.send(name, *args, &blk), typecode)
  end
end
gen_mutator(name) click to toggle source
# File lib/rmatrix/matrix.rb, line 426
def self.gen_mutator(name)
  define_method(name) do |*args, &blk|
    matrix.send(name, *args, &blk)
    self
  end
end
gen_typeconstructor(name) click to toggle source
# File lib/rmatrix/matrix.rb, line 471
def self.gen_typeconstructor(name)
  define_singleton_method(name) do
    ->(*source){ Matrix.new(source, name.to_s) }
  end
end
gen_vec_or_matrix_delegator(name) click to toggle source
# File lib/rmatrix/matrix.rb, line 433
def self.gen_vec_or_matrix_delegator(name)
  define_method(name) do |*args, &blk|
    case self
    when Vector then Vector.new(matrix.send(name, *args, &blk), typecode)
    when Matrix then Matrix.new(matrix.send(name, *args, &blk), typecode)
    end
  end
end
identity(size) click to toggle source
# File lib/rmatrix/matrix.rb, line 174
def self.identity(size)
  blank = self.blank(rows: size, columns: size)
  blank.diagonal(1)
end
new(source, typecode=Typecode::FLOAT, column_map: nil, row_map: nil, column_label_map: nil, row_label_map: nil) click to toggle source
# File lib/rmatrix/matrix.rb, line 18
def initialize(source, typecode=Typecode::FLOAT, column_map: nil, row_map: nil, column_label_map: nil, row_label_map: nil)
  self.typecode    = typecode
  self.narray      = two_dimensional(source, typecode)
  self.row_map     = row_map
  self.column_map  = column_map
end
ones(rows: 1, columns: 1) click to toggle source
# File lib/rmatrix/matrix.rb, line 179
def self.ones(rows: 1, columns: 1)
  self.blank(rows: rows, columns: columns, initial: 1)
end
seed(seed) click to toggle source
# File lib/rmatrix/matrix.rb, line 510
def self.seed(seed)
  NArray.srand(seed)
end
translate_op(op) click to toggle source
# File lib/rmatrix/matrix.rb, line 482
def self.translate_op(op)
  OPERATIONS_MAP.fetch(op, op)
end

Public Instance Methods

*(other) click to toggle source
# File lib/rmatrix/matrix.rb, line 302
def *(other)
  if other.kind_of?(Matrix)
    raise "Matrix A columns(#{self.columns}) != Matrix B rows(#{other.columns})" if other.rows != self.columns
    Matrix.new(self.matrix * other.matrix, typecode)
  else
    self.class.new(apply_scalar(:*, other), typecode)
  end
end
==(other) click to toggle source
# File lib/rmatrix/matrix.rb, line 315
def ==(other)
  self.narray == Matrix[other].narray
end
A()
Alias for: adjoint
C(*args)
Alias for: cofactor_matrix
D()
Alias for: determinant
M(x,y)
Alias for: minor
T()
Alias for: transpose
_dump(level) click to toggle source
# File lib/rmatrix/matrix.rb, line 58
def _dump(level)
  narray.to_s << ':' << columns.to_s << ':' << rows.to_s << ':' << narray.typecode.to_s
end
abs() click to toggle source
# File lib/rmatrix/matrix.rb, line 148
def abs
  (self ** 2) ** 0.5
end
adjoint() click to toggle source
# File lib/rmatrix/matrix.rb, line 298
def adjoint
  self.cofactor_matrix.transpose
end
Also aliased as: A
box_lines(lines, add_dots) click to toggle source
# File lib/rmatrix/matrix.rb, line 323
def box_lines(lines, add_dots)
  "[#{lines.map{|l| "[#{l}#{add_dots ? ' ...' : '' }]"}.join(",\n  ")}]"
end
coerce(other) click to toggle source
# File lib/rmatrix/matrix.rb, line 152
def coerce(other)
  self.invert_next_operation = true
  [self, other]
end
cofactor_matrix(*args) click to toggle source
# File lib/rmatrix/matrix.rb, line 273
def cofactor_matrix(*args)
  return cofactor(*args) if args.length == 2

  result = []
  rows.times do |i|
    result << []
    columns.times do |j|
      result[i] << cofactor(i, j)
    end
  end
  return Matrix.new(result, typecode)
end
Also aliased as: C
cols()
Alias for: columns
column_map=(column_map) click to toggle source
# File lib/rmatrix/matrix.rb, line 30
def column_map=(column_map)
  @column_map = parse_map(column_map)
  @column_label_map = @column_map.invert unless !@column_map || @column_map.default_proc
end
columns() click to toggle source
# File lib/rmatrix/matrix.rb, line 165
def columns
  self.shape.first
end
Also aliased as: cols
concat(*others, rows: true) click to toggle source
# File lib/rmatrix/matrix.rb, line 191
def concat(*others, rows: true)
  others.map!{|o| Matrix === o ? o.narray : NArray.to_na(o)}

  joined = case rows
  when true
    # raise "Rows must match #{self.rows}, #{others.map(&:rows)}" unless [self.rows, *others.map(&:shape).map(&:last)].uniq.count.one?
    height = self.rows + others.map(&:shape).map(&:last).inject(:+)
    width  = others[0].shape.first
    joined = ::NArray.new(typecode, width, height)
    joined[true, 0...self.rows] = self.narray
    current_row = self.rows
    others.each do |slice|
      slice_height = slice.shape[1]
      joined[true, current_row...current_row+slice_height] = slice
      current_row += slice_height
    end
    joined
  else
    width  = self.columns + others.map(&:shape).map(&:first).inject(:+)
    height = others[0].shape.last
    joined = ::NArray.new(typecode, width, height)
    joined[0...self.columns, true] = self.narray
    current_col = self.columns
    others.each do |slice|
      slice_width = slice.shape[0]
      joined[current_col...current_col+slice_width, true] = slice
      current_col += slice_width
    end
    joined
    # raise "Rows must match #{self.columns}, #{others.map(&:columns)}" unless [self.columns, *others.map(&:columns)].uniq.count.one?
  end

  Matrix.new(joined, typecode)
end
condensed(sz=10, sig=6, vdots='\\vdots', cdots='\\cdots', ddots='\\ddots') click to toggle source
# File lib/rmatrix/matrix.rb, line 376
def condensed(sz=10, sig=6, vdots='\\vdots', cdots='\\cdots', ddots='\\ddots')
  width  = [sz, self.cols].min
  height = [sz, self.rows].min
  insert_cdots = self.cols > sz
  insert_vdots = self.rows > sz

  width  += 1 if insert_cdots
  height += 1 if insert_vdots

  blank = M.blank(rows: height, columns: width, typecode: Typecode::OBJECT)
  blank.narray[0...width, 0...height] = self.narray[0...width, 0...height]

  blank.narray[0...width, -1] = self.narray[0...width, -1]
  blank.narray[-1,0...height] = self.narray[-1, 0...height]

  blank.narray[0...width, -2] = vdots if insert_vdots
  blank.narray[-2, 0...height] = cdots if insert_cdots

  if insert_cdots && insert_vdots
    blank.narray[-2, -2] = ddots
    blank.narray[-1, -2] = vdots
    blank.narray[-2, -1] = cdots
    blank.narray[-1, -1] = self.narray[-1, -1]
  end

  blank.narray.to_a.map{|line| (sig ? Array(line).map{|v| Numeric === v ? to_significant_figures(v,sig) : v } : Array(line))}
end
determinant() click to toggle source
# File lib/rmatrix/matrix.rb, line 286
def determinant
  raise "Cannot calculate determinant of non-square matrix" unless columns == rows
  return self.raw[0, 0] * self.raw[1, 1]- self.raw[0, 1] * self.raw[1, 0] if(self.columns == 2)
  sign = 1
  det = 0
  self.columns.times do |i|
    det += sign * self.raw[0,i] * self.minor(0, i).determinant
    sign *= -1
  end
  return det
end
Also aliased as: D
diag(dim=0) click to toggle source
# File lib/rmatrix/matrix.rb, line 169
def diag(dim=0)
  raise "Must be square matrix" unless self.shape[0] == self.shape[1]
  Matrix.new((self.class.identity(self.shape[0]).mult self).sum(dim))
end
each(&block) click to toggle source
# File lib/rmatrix/matrix.rb, line 105
def each(&block)
  e = Enumerator.new do |enum|
    matrix.each do |elm|
      enum << elm
    end
  end
  block_given? ? e.each(&block) : e
end
each_column(&block) click to toggle source
# File lib/rmatrix/matrix.rb, line 114
def each_column(&block)
  e = Enumerator.new do |enum|
    (0...self.columns).each  do |i|
      enum << self.raw[true, i]
    end
  end
  block_given? ? e.each(&block) : e
end
each_row(&block) click to toggle source
# File lib/rmatrix/matrix.rb, line 123
def each_row(&block)
 e = Enumerator.new do |enum|
    (0...self.rows).each  do |i|
      enum << self.raw[i, true]
    end
  end
  block_given? ? e.each(&block) : e
end
flat_map(&block) click to toggle source
# File lib/rmatrix/matrix.rb, line 68
def flat_map(&block)
  map(&block).flatten(1)
end
gplot(type: 'lines', series_names: [], xrange: nil, yrange: nil, title: '', ylabel: '', xlabel: '', style: nil) { |ds| ... } click to toggle source
# File lib/rmatrix/plot.rb, line 2
def gplot(type: 'lines', series_names: [], xrange: nil, yrange: nil, title: '', ylabel: '', xlabel: '', style: nil)
  require 'gnuplot'
  require 'base64'
  output_file = Tempfile.new(['plt','.png']).path
  plot = nil
  Gnuplot.open do |gp|
    plot = Gnuplot::Plot.new( gp ) do |plot|

      plot.xrange "[#{xrange.begin}:#{xrange.end}]" if xrange
      plot.title  title
      plot.ylabel ylabel
      plot.xlabel xlabel
      plot.set("style", style) if style
      plot.terminal 'png size 1000,1000'

      x = (0..50).collect { |v| v.to_f }
      y = x.collect { |v| v ** 2 }

      plot.output(output_file)

      plot.data = self.each_row.map.with_index do |row, i|
        Gnuplot::DataSet.new(row.to_a) do |ds|
          ds.with = type
          ds.title = series_names[i] || ''
          yield ds if block_given?
        end
      end
    end
  end

  puts "\033]1337;File=inline=1:#{Base64.encode64(IO.read(output_file))}\a";
end
gruff(title: '', type: 'Line', labels:{}, series_names: [], hide_legend: false, theme: Gruff::Themes::RAILS_KEYNOTE) click to toggle source
# File lib/rmatrix/plot.rb, line 35
def gruff(title: '', type: 'Line', labels:{}, series_names: [], hide_legend: false, theme: Gruff::Themes::RAILS_KEYNOTE)
  require 'gruff'
  g = Gruff.const_get(type).new
  # g.theme = {
  #   :colors => ["#3366CC","#DC3912","#FF9900","#109618","#990099","#3B3EAC","#0099C6","#DD4477","#66AA00","#B82E2E","#316395","#994499","#22AA99","#AAAA11","#6633CC","#E67300","#8B0707","#329262","#5574A6","#3B3EAC"],
  #   :marker_color => '#dddddd',
  #   :font_color => 'black',
  #   :background_colors => ['white', '#acacac']
  #   # :background_image => File.expand_path(File.dirname(__FILE__) + "/../assets/backgrounds/43things.png")
  # }
  # g.hide_legend = true if hide_legend || series_names.empty? && self.rows.to_i > 10
  # g.title = title
  # g.labels = {}
  self.each_row.map.with_index do |row, i|
    series_name = (series_names[i] || i).to_s
    g.data series_name, row.to_a[0..5].map{|v| v.round(2)}
  end if self.rows
  fname = "/tmp/chrt-#{Random.rand(1000000...9999999)}.png"
  g.write(fname)
  puts "\033]1337;File=inline=1:#{Base64.encode64(g.to_blob)}\a";
end
inspect(sz: 10, sig: 6, names: RMatrix::Matrix.named_inspect) click to toggle source
# File lib/rmatrix/matrix.rb, line 339
def inspect(sz: 10, sig: 6, names: RMatrix::Matrix.named_inspect)
  desc = case
  when self.is_vector? then "Vector(#{self.length})"
  else "Matrix(#{rows} x #{columns})"
  end
  "#{desc}\n#{RMatrix::MatrixTable.new(self).to_s}"
end
is_vector?() click to toggle source
# File lib/rmatrix/matrix.rb, line 331
def is_vector?
  [rows, columns].include?(1)
end
join(other) click to toggle source
# File lib/rmatrix/matrix.rb, line 226
def join(other)
  case true
  when self.rows == 1 && other.rows == 1
    self.class.new(NArray.to_na([self.narray,other.narray]).to_type(self.typecode).reshape(self.columns + other.columns, 1))
  when self.columns == 1 && other.columns == 1
    self.class.new(NArray.to_na([self.narray,other.narray]).to_type(self.typecode).reshape(1, self.rows + other.rows))
  else
    raise "Couldn't join mismatched dimensions"
  end
end
length()
Alias for: size
map(flatten: true) { |x| ... } click to toggle source
# File lib/rmatrix/matrix.rb, line 62
def map(flatten: true)
  narray.to_type(RMatrix::Matrix::Typecode::OBJECT).map do |x|
    yield x
  end.to_a
end
mask() { |elm) ? 0 : elm| ... } click to toggle source
# File lib/rmatrix/matrix.rb, line 142
def mask
  mmap do |elm|
    (yield elm) ? 0 : elm
  end
end
matrix() click to toggle source
# File lib/rmatrix/matrix.rb, line 44
def matrix
  @matrix ||= narray.empty? ? narray : NMatrix.refer(narray)
end
minor(x,y) click to toggle source
# File lib/rmatrix/matrix.rb, line 269
def minor(x,y)
  return self.delete_at(y,x)
end
Also aliased as: M
mmap() { |elm| ... } click to toggle source
# File lib/rmatrix/matrix.rb, line 132
def mmap
  return self.class.new(matrix, typecode) if shape.length == 0
  as_na = NArray.to_na(
    matrix.each.map do |elm|
      yield elm
    end
  ).to_type(typecode)
  self.class.new(as_na.reshape(*shape), typecode)
end
mult(other) click to toggle source
# File lib/rmatrix/matrix.rb, line 311
def mult(other)
  self.class.new(self.narray * other.narray, typecode)
end
parse_map(map, invert: false) click to toggle source
# File lib/rmatrix/matrix.rb, line 35
def parse_map(map, invert: false)
  case map
  when nil then map
  when Array then invert ? map.each.with_index.map.to_h.invert : map.each.with_index.map.to_h
  when Hash then map
  else raise 'Invalid map type encountered'
  end
end
round(dp) click to toggle source
# File lib/rmatrix/matrix.rb, line 327
def round(dp)
  mmap{|x| x.round(dp) }
end
row_map=(row_map) click to toggle source
# File lib/rmatrix/matrix.rb, line 25
def row_map=(row_map)
  @row_map = parse_map(row_map)
  @row_label_map = @row_map.invert unless !@row_map || @row_map.default_proc
end
rows() click to toggle source
# File lib/rmatrix/matrix.rb, line 161
def rows
  self.shape.last
end
set_all(value) click to toggle source
# File lib/rmatrix/matrix.rb, line 54
def set_all(value)
  narray[]=(value)
end
size() click to toggle source
# File lib/rmatrix/matrix.rb, line 157
def size
  self.shape.inject(:*).to_i
end
Also aliased as: length
sum(dim=nil) click to toggle source
# File lib/rmatrix/matrix.rb, line 448
def sum(dim=nil)
  case dim
  when nil then
    res = self.narray.sum
    NArray === res ? Matrix.new(0, typecode)[0] : res
  else Matrix.new(self.matrix.sum(dim), typecode)
  end
end
sum_columns() click to toggle source
# File lib/rmatrix/matrix.rb, line 187
def sum_columns
  sum(0)
end
sum_rows() click to toggle source
# File lib/rmatrix/matrix.rb, line 183
def sum_rows
  sum(1)
end
threed_gplot(pm3d: false) click to toggle source
# File lib/rmatrix/plot.rb, line 57
def threed_gplot(pm3d: false)
  require 'gnuplot'
  output_file = Tempfile.new(['plt','.png']).path
  plot = nil
  Gnuplot.open do |gp|
    plot = Gnuplot::SPlot.new( gp ) do |plot|

      case IRuby::Kernel.instance
      when nil
        puts "Setting output"
        plot.terminal 'png'
        plot.output(output_file)
      end
      # see sin_wave.rb
      plot.pm3d if pm3d
      plot.hidden3d

      plot.data << Gnuplot::DataSet.new( self.to_a ) do |ds|
        ds.with = 'lines'
        ds.matrix = true
      end

    end
  end

  puts "\033]1337;File=inline=1:#{Base64.encode64(IO.read(output_file))}\a";
end
to_a() click to toggle source
# File lib/rmatrix/matrix.rb, line 506
def to_a
  return narray.to_a
end
to_f() click to toggle source
# File lib/rmatrix/matrix.rb, line 72
def to_f
  if length === 1
    self.narray[0].to_f
  else
    raise "Can only call to_f on vectors of length 1"
  end
end
to_i() click to toggle source
# File lib/rmatrix/matrix.rb, line 80
def to_i
  if length === 1
    self.narray[0].to_i
  else
    raise "Can only call to_i on vectors of length 1"
  end
end
to_m() click to toggle source
# File lib/rmatrix/matrix.rb, line 514
def to_m
  self
end
to_s() click to toggle source
# File lib/rmatrix/matrix.rb, line 319
def to_s
  inspect
end
to_significant_figures(x, p) click to toggle source
# File lib/rmatrix/matrix.rb, line 335
def to_significant_figures(x, p)
  ("%-.#{p}e" % x).gsub(/0+e/,'e').gsub('.e+00','').gsub('e+00','')
end
to_tex(sz = 10, sig=6) click to toggle source
# File lib/rmatrix/matrix.rb, line 347
    def to_tex(sz = 10, sig=6)
      values = condensed(sz, sig)
      column_headers = column_label_map ? values[0].map.with_index do |v, i|
        case v
        when '\\cdots' then '\\cdots'
        else (column_label_map && column_label_map[i]) || i
        end
      end : []

      row_headers = row_label_map ? values.map.with_index do |v, i|
        case v[0]
        when '\\vdots' then '\\vdots'
        else (row_label_map && row_label_map[i]) || i
        end
      end : []

      <<-TEX
$
\\begin{array}{c} &
\\begin{array}{c} #{column_headers.join(" & ")} \\end{array}\\\\
\\begin{array}{c} #{row_headers.join(" \\\\ ")} \\end{array} &
  \\left(\\begin{array}{ccc}
    #{values.map{|line| line.join(" & ")}.join(" \\\\ ")}
  \\end{array}\\right)
\\end{array}
$
TEX
    end
to_type(type) click to toggle source
# File lib/rmatrix/matrix.rb, line 457
def to_type(type)
  self.class.new(narray.to_type(type), type)
end
transpose() click to toggle source
# File lib/rmatrix/matrix.rb, line 404
def transpose()
  Matrix.new(self.matrix.transpose, typecode, column_map: self.row_map, row_map: self.column_map, column_label_map: self.row_label_map, row_label_map: self.column_label_map)
end
Also aliased as: T
two_dimensional(source, type) click to toggle source
# File lib/rmatrix/matrix.rb, line 237
def two_dimensional(source, type)
  case source
  when NArray
    if NMatrix === source
      @matrix = source
      source = NArray.refer(source)
    end
  when Numeric
    source = NArray.to_na([source])
  else
    source = NArray.to_na(source)
    if type != RMatrix::Matrix::Typecode::OBJECT &&
      source.typecode == RMatrix::Matrix::Typecode::OBJECT &&
      RMatrix::Matrix === source[0]
      source = NArray.to_na(source.map(&:to_a).to_a).to_type(typecode)
    end
    source
  end

  source = source.to_type(type) unless type == source.typecode

  case source.dim
  when 1
    source.reshape(source.length, 1)
  when 2, 0
    source
  else
    raise "Source for matrix must be either one or two dimensional" unless source.shape[2..-1].all?{|x| x == 1}
    source.reshape(source.shape[0], source.shape[1])
  end
end
zip(*others) click to toggle source
Calls superclass method
# File lib/rmatrix/matrix.rb, line 422
def zip(*others)
  Matrix.new(super(*others), self.typecode)
end

Private Instance Methods

apply_elementwise(op, other) click to toggle source
# File lib/rmatrix/matrix.rb, line 536
def apply_elementwise(op, other)
  if test_inverse
    other.narray.send(op, self.narray)
  else
    narray.send(op, other.narray)
  end
end
apply_scalar(op, other) click to toggle source
# File lib/rmatrix/matrix.rb, line 544
def apply_scalar(op, other)
  if test_inverse
    other.send(op, self.narray)
  else
    narray.send(op, other)
  end
end
cofactor(i, j) click to toggle source
# File lib/rmatrix/matrix.rb, line 530
def cofactor(i, j)
  minor = self.minor(i, j)
  sign = ((i * self.columns + j) % 2).zero? ? 1 : -1;
  return sign * minor.determinant
end
test_inverse() click to toggle source
# File lib/rmatrix/matrix.rb, line 523
def test_inverse
  if self.invert_next_operation
    self.invert_next_operation = false
    return true
  end
end