Files
gonum/matrix/conv/conv.go
2017-05-25 16:07:18 +09:30

143 lines
3.9 KiB
Go

// Copyright ©2015 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package conv provides matrix type interconversion utilities.
package conv // import "gonum.org/v1/gonum/matrix/conv"
import (
"gonum.org/v1/gonum/matrix"
"gonum.org/v1/gonum/matrix/cmat128"
"gonum.org/v1/gonum/matrix/mat64"
)
// Complex is a complex matrix constructed from two real matrices.
type Complex struct {
// r and i are not exposed to ensure that
// their dimensions can not be altered by
// clients behind our back.
r, i mat64.Matrix
// imagSign holds the sign of the imaginary
// part of the Complex. Valid values are 1 and -1.
imagSign float64
}
var (
_ Realer = Complex{}
_ Imager = Complex{}
)
// NewComplex returns a complex matrix constructed from r and i. At least one of
// r or i must be non-nil otherwise NewComplex will panic. If one of the inputs
// is nil, that part of the complex number will be zero when returned by At.
// If both are non-nil but differ in their sizes, NewComplex will panic.
func NewComplex(r, i mat64.Matrix) Complex {
if r == nil && i == nil {
panic("conv: no matrix")
} else if r != nil && i != nil {
rr, rc := r.Dims()
ir, ic := i.Dims()
if rr != ir || rc != ic {
panic(matrix.ErrShape)
}
}
return Complex{r: r, i: i, imagSign: 1}
}
// Dims returns the number of rows and columns in the matrix.
func (m Complex) Dims() (r, c int) {
if m.r == nil {
return m.i.Dims()
}
return m.r.Dims()
}
// At returns the element at row i, column j.
func (m Complex) At(i, j int) complex128 {
if m.i == nil {
return complex(m.r.At(i, j), 0)
}
if m.r == nil {
return complex(0, m.imagSign*m.i.At(i, j))
}
return complex(m.r.At(i, j), m.imagSign*m.i.At(i, j))
}
// H performs an implicit transpose.
func (m Complex) H() cmat128.Matrix {
if m.i == nil {
return Complex{r: m.r.T()}
}
if m.r == nil {
return Complex{i: m.i.T(), imagSign: -m.imagSign}
}
return Complex{r: m.r.T(), i: m.i.T(), imagSign: -m.imagSign}
}
// Real returns the real part of the receiver.
func (m Complex) Real() mat64.Matrix { return m.r }
// Imag returns the imaginary part of the receiver.
func (m Complex) Imag() mat64.Matrix { return m.i }
// Realer is a complex matrix that can return its real part.
type Realer interface {
Real() mat64.Matrix
}
// Imager is a complex matrix that can return its imaginary part.
type Imager interface {
Imag() mat64.Matrix
}
// Real is the real part of a complex matrix.
type Real struct {
matrix cmat128.Matrix
}
// NewReal returns a mat64.Matrix representing the real part of m. If m is a Realer,
// the real part is returned.
func NewReal(m cmat128.Matrix) mat64.Matrix {
if m, ok := m.(Realer); ok {
return m.Real()
}
return Real{m}
}
// Dims returns the number of rows and columns in the matrix.
func (m Real) Dims() (r, c int) { return m.matrix.Dims() }
// At returns the element at row i, column j.
func (m Real) At(i, j int) float64 { return real(m.matrix.At(i, j)) }
// T performs an implicit transpose.
func (m Real) T() mat64.Matrix { return Real{m.matrix.H()} }
// Imag is the imaginary part of a complex matrix.
type Imag struct {
matrix cmat128.Matrix
// conjSign holds the sign of the matrix.
// Valid values are 1 and -1.
conjSign float64
}
// NewImag returns a mat64.Matrix representing the imaginary part of m. If m is an Imager,
// the imaginary part is returned.
func NewImag(m cmat128.Matrix) mat64.Matrix {
if m, ok := m.(Imager); ok {
return m.Imag()
}
return Imag{matrix: m, conjSign: 1}
}
// Dims returns the number of rows and columns in the matrix.
func (m Imag) Dims() (r, c int) { return m.matrix.Dims() }
// At returns the element at row i, column j.
func (m Imag) At(i, j int) float64 { return m.conjSign * imag(m.matrix.At(i, j)) }
// T performs an implicit transpose.
func (m Imag) T() mat64.Matrix { return Imag{matrix: m.matrix.H(), conjSign: -m.conjSign} }