mat: add IsZero method to resetable types

This commit is contained in:
kortschak
2017-06-21 09:58:26 +09:30
committed by Dan Kortschak
parent 08e1f7dfc1
commit 01a0286e0f
9 changed files with 45 additions and 24 deletions

View File

@@ -475,5 +475,5 @@ func (c *Cholesky) isZero() bool {
} }
func (c *Cholesky) valid() bool { func (c *Cholesky) valid() bool {
return !c.isZero() && !c.chol.isZero() return !c.isZero() && !c.chol.IsZero()
} }

View File

@@ -69,7 +69,7 @@ func (m *Dense) reuseAs(r, c int) {
// Panic as a string, not a mat.Error. // Panic as a string, not a mat.Error.
panic("mat: caps not correctly set") panic("mat: caps not correctly set")
} }
if m.isZero() { if m.IsZero() {
m.mat = blas64.General{ m.mat = blas64.General{
Rows: r, Rows: r,
Cols: c, Cols: c,
@@ -95,7 +95,7 @@ func (m *Dense) reuseAsZeroed(r, c int) {
// Panic as a string, not a mat.Error. // Panic as a string, not a mat.Error.
panic("mat: caps not correctly set") panic("mat: caps not correctly set")
} }
if m.isZero() { if m.IsZero() {
m.mat = blas64.General{ m.mat = blas64.General{
Rows: r, Rows: r,
Cols: c, Cols: c,
@@ -147,7 +147,9 @@ func (m *Dense) Reset() {
m.mat.Data = m.mat.Data[:0] m.mat.Data = m.mat.Data[:0]
} }
func (m *Dense) isZero() bool { // IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the
// receiver for size-restricted operations. Dense matrices can be zeroed using Reset.
func (m *Dense) IsZero() bool {
// It must be the case that m.Dims() returns // It must be the case that m.Dims() returns
// zeros in this case. See comment in Reset(). // zeros in this case. See comment in Reset().
return m.mat.Stride == 0 return m.mat.Stride == 0

View File

@@ -467,7 +467,7 @@ func (m *Dense) Exp(a Matrix) {
} }
var w *Dense var w *Dense
if m.isZero() { if m.IsZero() {
m.reuseAsZeroed(r, r) m.reuseAsZeroed(r, r)
w = m w = m
} else { } else {
@@ -696,7 +696,7 @@ func (m *Dense) Outer(alpha float64, x, y *Vector) {
// Panic as a string, not a mat.Error. // Panic as a string, not a mat.Error.
panic("mat: caps not correctly set") panic("mat: caps not correctly set")
} }
if m.isZero() { if m.IsZero() {
m.mat = blas64.General{ m.mat = blas64.General{
Rows: r, Rows: r,
Cols: c, Cols: c,

View File

@@ -36,11 +36,24 @@
// zero.Copy(a) // zero.Copy(a)
// //
// Receivers must be the correct size for the matrix operations, otherwise the // Receivers must be the correct size for the matrix operations, otherwise the
// operation will panic. As a special case for convenience, a zero-sized matrix // operation will panic. As a special case for convenience, a zero-value matrix
// will be modified to have the correct size, allocating data if necessary. // will be modified to have the correct size, allocating data if necessary.
// var c mat.Dense // construct a new zero-sized matrix // var c mat.Dense // construct a new zero-sized matrix
// c.Mul(a, a) // c is automatically adjusted to be 6×6 // c.Mul(a, a) // c is automatically adjusted to be 6×6
// //
// Zero-value of a matrix
//
// A zero-value matrix is either the Go language definition of a zero-value or
// is a zero-sized matrix with zero-length stride. Matrix implementations may have
// a Reset method to revert the receiver into a zero-valued matrix and an IsZero
// method that returns whether the matrix is zero-valued.
// So the following will all result in a zero-value matrix.
// - var a mat.Dense
// - a := NewDense(0, 0, make([]float64, 0, 100))
// - a.Reset()
// A zero-value matrix can not be sliced even if it does have an adequately sized
// backing data slice, but can be expanded using its Grow method if it exists.
//
// The Matrix Interfaces // The Matrix Interfaces
// //
// The Matrix interface is the common link between the concrete types of real // The Matrix interface is the common link between the concrete types of real

View File

@@ -109,7 +109,7 @@ func (m Dense) MarshalBinaryTo(w io.Writer) (int, error) {
// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so // UnmarshalBinary does not limit the size of the unmarshaled matrix, and so
// it should not be used on untrusted data. // it should not be used on untrusted data.
func (m *Dense) UnmarshalBinary(data []byte) error { func (m *Dense) UnmarshalBinary(data []byte) error {
if !m.isZero() { if !m.IsZero() {
panic("mat: unmarshal into non-zero matrix") panic("mat: unmarshal into non-zero matrix")
} }
@@ -158,7 +158,7 @@ func (m *Dense) UnmarshalBinary(data []byte) error {
// UnmarshalBinary does not limit the size of the unmarshaled matrix, and so // UnmarshalBinary does not limit the size of the unmarshaled matrix, and so
// it should not be used on untrusted data. // it should not be used on untrusted data.
func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) { func (m *Dense) UnmarshalBinaryFrom(r io.Reader) (int, error) {
if !m.isZero() { if !m.IsZero() {
panic("mat: unmarshal into non-zero matrix") panic("mat: unmarshal into non-zero matrix")
} }
@@ -268,7 +268,7 @@ func (v Vector) MarshalBinaryTo(w io.Writer) (int, error) {
// UnmarshalBinary does not limit the size of the unmarshaled vector, and so // UnmarshalBinary does not limit the size of the unmarshaled vector, and so
// it should not be used on untrusted data. // it should not be used on untrusted data.
func (v *Vector) UnmarshalBinary(data []byte) error { func (v *Vector) UnmarshalBinary(data []byte) error {
if !v.isZero() { if !v.IsZero() {
panic("mat: unmarshal into non-zero vector") panic("mat: unmarshal into non-zero vector")
} }
@@ -301,7 +301,7 @@ func (v *Vector) UnmarshalBinary(data []byte) error {
// See MarshalBinary for the on-disk layout. // See MarshalBinary for the on-disk layout.
// See UnmarshalBinary for the list of sanity checks performed on the input. // See UnmarshalBinary for the list of sanity checks performed on the input.
func (v *Vector) UnmarshalBinaryFrom(r io.Reader) (int, error) { func (v *Vector) UnmarshalBinaryFrom(r io.Reader) (int, error) {
if !v.isZero() { if !v.IsZero() {
panic("mat: unmarshal into non-zero vector") panic("mat: unmarshal into non-zero vector")
} }

View File

@@ -71,7 +71,7 @@ func newMultiplier(m *Dense, factors []Matrix) *multiplier {
// allocate data for m. // allocate data for m.
r, c := m.Dims() r, c := m.Dims()
fr, fc := factors[0].Dims() // newMultiplier is only called with len(factors) > 2. fr, fc := factors[0].Dims() // newMultiplier is only called with len(factors) > 2.
if !m.isZero() { if !m.IsZero() {
if fr != r { if fr != r {
panic(ErrShape) panic(ErrShape)
} }

View File

@@ -126,7 +126,9 @@ func (s *SymDense) Reset() {
s.mat.Data = s.mat.Data[:0] s.mat.Data = s.mat.Data[:0]
} }
func (s *SymDense) isZero() bool { // IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the
// receiver for size-restricted operations. SymDense matrices can be zeroed using Reset.
func (s *SymDense) IsZero() bool {
// It must be the case that m.Dims() returns // It must be the case that m.Dims() returns
// zeros in this case. See comment in Reset(). // zeros in this case. See comment in Reset().
return s.mat.N == 0 return s.mat.N == 0
@@ -138,7 +140,7 @@ func (s *SymDense) reuseAs(n int) {
if s.mat.N > s.cap { if s.mat.N > s.cap {
panic(badSymCap) panic(badSymCap)
} }
if s.isZero() { if s.IsZero() {
s.mat = blas64.Symmetric{ s.mat = blas64.Symmetric{
N: n, N: n,
Stride: n, Stride: n,
@@ -283,7 +285,7 @@ func (s *SymDense) SymRankK(a Symmetric, alpha float64, x Matrix) {
func (s *SymDense) SymOuterK(alpha float64, x Matrix) { func (s *SymDense) SymOuterK(alpha float64, x Matrix) {
n, _ := x.Dims() n, _ := x.Dims()
switch { switch {
case s.isZero(): case s.IsZero():
s.mat = blas64.Symmetric{ s.mat = blas64.Symmetric{
N: n, N: n,
Stride: n, Stride: n,

View File

@@ -135,7 +135,7 @@ func (t *TriDense) Dims() (r, c int) {
// Triangle returns the dimension of t and its orientation. The returned // Triangle returns the dimension of t and its orientation. The returned
// orientation is only valid when n is not zero. // orientation is only valid when n is not zero.
func (t *TriDense) Triangle() (n int, kind TriKind) { func (t *TriDense) Triangle() (n int, kind TriKind) {
return t.mat.N, TriKind(!t.isZero()) && t.triKind() return t.mat.N, TriKind(!t.IsZero()) && t.triKind()
} }
func (t *TriDense) isUpper() bool { func (t *TriDense) isUpper() bool {
@@ -200,7 +200,9 @@ func (t *TriDense) Reset() {
t.mat.Data = t.mat.Data[:0] t.mat.Data = t.mat.Data[:0]
} }
func (t *TriDense) isZero() bool { // IsZero returns whether the receiver is zero-sized. Zero-sized matrices can be the
// receiver for size-restricted operations. TriDense matrices can be zeroed using Reset.
func (t *TriDense) IsZero() bool {
// It must be the case that t.Dims() returns // It must be the case that t.Dims() returns
// zeros in this case. See comment in Reset(). // zeros in this case. See comment in Reset().
return t.mat.Stride == 0 return t.mat.Stride == 0
@@ -227,7 +229,7 @@ func (t *TriDense) reuseAs(n int, kind TriKind) {
if t.mat.N > t.cap { if t.mat.N > t.cap {
panic(badTriCap) panic(badTriCap)
} }
if t.isZero() { if t.IsZero() {
t.mat = blas64.Triangular{ t.mat = blas64.Triangular{
N: n, N: n,
Stride: n, Stride: n,

View File

@@ -67,7 +67,7 @@ func (v *Vector) SliceVec(i, k int) *Vector {
// Dims returns the number of rows and columns in the matrix. Columns is always 1 // Dims returns the number of rows and columns in the matrix. Columns is always 1
// for a non-Reset vector. // for a non-Reset vector.
func (v *Vector) Dims() (r, c int) { func (v *Vector) Dims() (r, c int) {
if v.isZero() { if v.IsZero() {
return 0, 0 return 0, 0
} }
return v.n, 1 return v.n, 1
@@ -76,7 +76,7 @@ func (v *Vector) Dims() (r, c int) {
// Caps returns the number of rows and columns in the backing matrix. Columns is always 1 // Caps returns the number of rows and columns in the backing matrix. Columns is always 1
// for a non-Reset vector. // for a non-Reset vector.
func (v *Vector) Caps() (r, c int) { func (v *Vector) Caps() (r, c int) {
if v.isZero() { if v.IsZero() {
return 0, 0 return 0, 0
} }
return v.Cap(), 1 return v.Cap(), 1
@@ -89,7 +89,7 @@ func (v *Vector) Len() int {
// Cap returns the capacity of the vector. // Cap returns the capacity of the vector.
func (v *Vector) Cap() int { func (v *Vector) Cap() int {
if v.isZero() { if v.IsZero() {
return 0 return 0
} }
return (cap(v.mat.Data)-1)/v.mat.Inc + 1 return (cap(v.mat.Data)-1)/v.mat.Inc + 1
@@ -426,7 +426,7 @@ func (v *Vector) MulVec(a Matrix, b *Vector) {
// reuseAs resizes an empty vector to a r×1 vector, // reuseAs resizes an empty vector to a r×1 vector,
// or checks that a non-empty matrix is r×1. // or checks that a non-empty matrix is r×1.
func (v *Vector) reuseAs(r int) { func (v *Vector) reuseAs(r int) {
if v.isZero() { if v.IsZero() {
v.mat = blas64.Vector{ v.mat = blas64.Vector{
Inc: 1, Inc: 1,
Data: use(v.mat.Data, r), Data: use(v.mat.Data, r),
@@ -439,7 +439,9 @@ func (v *Vector) reuseAs(r int) {
} }
} }
func (v *Vector) isZero() bool { // IsZero returns whether the receiver is zero-sized. Zero-sized vectors can be the
// receiver for size-restricted operations. Vectors can be zeroed using Reset.
func (v *Vector) IsZero() bool {
// It must be the case that v.Dims() returns // It must be the case that v.Dims() returns
// zeros in this case. See comment in Reset(). // zeros in this case. See comment in Reset().
return v.mat.Inc == 0 return v.mat.Inc == 0