
  	   ˆ¾È0ÁÆ  	   ˆ¾È0ÁÆ  $   ˆl–ßi~”ja,je@7q¦n2â˜´oÉ„iÀ>ÿÅÂÇ ?÷     # encoding: utf-8
#
# = matrix.rb
#
# An implementation of Matrix and Vector classes.
#
# See classes Matrix and Vector for documentation.
#
# Current Maintainer:: Marc-AndrÃ© Lafortune
# Original Author:: Keiju ISHITSUKA
# Original Documentation:: Gavin Sinclair (sourced from <i>Ruby in a Nutshell</i> (Matsumoto, O'Reilly))
##

require "e2mmap.rb"

module ExceptionForMatrix # :nodoc:
  extend Exception2MessageMapper
  def_e2message(TypeError, "wrong argument type %s (expected %s)")
  def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")

  def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
  def_exception("ErrNotRegular", "Not Regular Matrix")
  def_exception("ErrOperationNotDefined", "Operation(%s) can\\'t be defined: %s op %s")
  def_exception("ErrOperationNotImplemented", "Sorry, Operation(%s) not implemented: %s op %s")
end

#
# The +Matrix+ class represents a mathematical matrix. It provides methods for creating
# matrices, operating on them arithmetically and algebraically,
# and determining their mathematical properties (trace, rank, inverse, determinant).
#
# == Method Catalogue
#
# To create a matrix:
# * Matrix[*rows]
# * Matrix.[](*rows)
# * Matrix.rows(rows, copy = true)
# * Matrix.columns(columns)
# * Matrix.build(row_count, column_count, &block)
# * Matrix.diagonal(*values)
# * Matrix.scalar(n, value)
# * Matrix.identity(n)
# * Matrix.unit(n)
# * Matrix.I(n)
# * Matrix.zero(n)
# * Matrix.row_vector(row)
# * Matrix.column_vector(column)
#
# To access Matrix elements/columns/rows/submatrices/properties:
# * #[](i, j)
# * #row_count (row_size)
# * #column_count (column_size)
# * #row(i)
# * #column(j)
# * #collect
# * #map
# * #each
# * #each_with_index
# * #find_index
# * #minor(*param)
#
# Properties of a matrix:
# * #diagonal?
# * #empty?
# * #hermitian?
# * #lower_triangular?
# * #normal?
# * #orthogonal?
# * #permutation?
# * #real?
# * #regular?
# * #singular?
# * #square?
# * #symmetric?
# * #unitary?
# * #upper_triangular?
# * #zero?
#
# Matrix arithmetic:
# * #*(m)
# * #+(m)
# * #-(m)
# * #/(m)
# * #inverse
# * #inv
# * #**
#
# Matrix functions:
# * #determinant
# * #det
# * #rank
# * #round
# * #trace
# * #tr
# * #transpose
# * #t
#
# Matrix decompositions:
# * #eigen
# * #eigensystem
# * #lup
# * #lup_decomposition
#
# Complex arithmetic:
# * conj
# * conjugate
# * imag
# * imaginary
# * real
# * rect
# * rectangular
#
# Conversion to other data types:
# * #coerce(other)
# * #row_vectors
# * #column_vectors
# * #to_a
#
# String representations:
# * #to_s
# * #inspect
#
class Matrix
  include Enumerable
  include ExceptionForMatrix
  autoload :EigenvalueDecomposition, "matrix/eigenvalue_decomposition"
  autoload :LUPDecomposition, "matrix/lup_decomposition"

  # instance creations
  private_class_method :new
  attr_reader :rows
  protected :rows

  #
  # Creates a matrix where each argument is a row.
  #   Matrix[ [25, 93], [-1, 66] ]
  #      =>  25 93
  #          -1 66
  #
  def Matrix.[](*rows)
    rows(rows, false)
  end

  #
  # Creates a matrix where +rows+ is an array of arrays, each of which is a row
  # of the matrix.  If the optional argument +copy+ is false, use the given
  # arrays as the internal structure of the matrix without copying.
  #   Matrix.rows([[25, 93], [-1, 66]])
  #      =>  25 93
  #          -1 66
  #
  def Matrix.rows(rows, copy = true)
    rows = convert_to_array(rows)
    rows.map! do |row|
      convert_to_array(row, copy)
    end
    size = (rows[0] || []).size
    rows.each do |row|
      raise ErrDimensionMismatch, "row size differs (#{row.size} should be #{size})" unless row.size == size
    end
    new rows, size
  end

  #
  # Creates a matrix using +columns+ as an array of column vectors.
  #   Matrix.columns([[25, 93], [-1, 66]])
  #      =>  25 -1
  #          93 66
  #
  def Matrix.columns(columns)
    rows(columns, false).transpose
  end

  #
  # Creates a matrix of size +row_count+ x +column_count+.
  # It fills the values by callin